เมนู

วันศุกร์ที่ 12 สิงหาคม พ.ศ. 2559

Pinguino กับ 7-segment บน Multifunction Shield


               หลังจากได้ลองค้นดูว่ายังมี shield อะไรเก็บไว้อยู่บ้างก็เจอว่ายังมีตัว Multifunction Shield ที่ดูน่าสนใจเอามาเขียนโปรแกรมกับบอร์ด Pinguino 8 ที่ดูน่าสนใจที่สุดบนบอร์ดก็ต้องเป็นเจ้า 7-segment 4 หลักที่เชื่อมต่ออยู่กับ IC serial-to-parallel 74HC595 เมื่อพอลองหาข้อมูลจากเว็ปดูก็ไปได้ข้อมูลจากลิ้งค์ข้างล่างนี้ 
https://wiki.eprolabs.com/index.php?title=Multi-functional_Learning_Board_for_Arduino
รูปที่ 1 Schematic ส่วนของ 7-Segment กับ 74HC595
รูปที่ 2 หมายเลขพินของบอร์ด Pinguino 8
              พอดูที่ schematic จะเห็นว่า 7-segment 4 หลักที่อยู่บนตัว shield นั้นจะมี IC 74HC595 จำนวน 2 ตัวต่อ drive อยู่ โดยตัวแรก( U2) จะเป็นตัวเลือกว่าจะให้ 7-segment หลักไหนแสดงผล ส่วนตัว U3 จะเป็นตัวขับให้แสดงเป็นตัวเลขต่างๆ  อินพุตจะเริ่มจากตัว U2 โดยขา SDI (ขา data)จะต่ออยู่กับพิน 8 ของ Arduino ส่วนขา SFTCLK(ขา clock)จะต่อกับพิน 7 และสุดท้ายขา LCHCLK(ขา latch)จะต่อกับพิน 4 ทีนี้เมื่อเรารู้ตำแหน่งที่เชื่อต่อกับ Arduino แล้ว เมื่อเราต้องการใช้บอร์ด Pinguino 8 แทนเราก็ต้องมาดูว่าที่ตำแหน่งเดียวกันนั้นบนบอร์ด Pinguino 8 เป็นพินหมายเลขอะไร จากในรูปที่ 2 จะเห็นว่าเป็นพินหมายเลข 5, 16, และ 24 ตามลำดับ ดังนั้นเพื่อให้ง่ายในการจำและเขียนโค้ดเราจึงจะ define พินทั้งสามนี้ไว้ดังนี้

1:  /* Define shift register pins used for seven segment display */  
2:  #define LATCH_DIO   24  
3:  #define CLK_DIO     16  
4:  #define DATA_DIO    5  

               จากนั้นเราก็ต้องมากำหนดค่าคงที่ที่เราจะส่งออกไปแล้วทำให้ 7-segment ติดสว่างแสดงเป็นตัวเลข 0-9 เมื่อเราพิจารณาที่ schematic โดยเฉพาะที่ U3 ซึ่งต่อเข้ากับ 7-segment ที่ตำแหน่ง a-h ตามลำดับแล้วโดยเมื่อเราส่ง logic 0 ออกไปที่พินใดๆ(a-h) ก็จะทำให้ segment นั้นๆติดสว่าง(เป็น common Anode) ยกตัวอย่างเช่นต้องการให้เลข 0 ติดสว่างจะต้องให้ logic 0 ที่พิน a, b, c, d, e, f และให้ logic 1 ที่พิน g กับ h และค่า binary นี้จะถูกส่งออกไปทีละบิต โดยถ้ายึดตามโค้ดตัวอย่างของ Arduino ที่เลือกส่งบิต MSB(Most Significant Bit) ออกไปก่อนเราก็จะได้ค่าเป็น 0xC0  และหมายเลขอื่นๆก็ใช้วิธีคิดแบบเดียวกันครับ โดยค่าคงที่ทั้งสิบตัวจะมีค่าเป็นดังนี้

 /* Segment byte maps for numbers 0 to 9 */  
 const byte SEGMENT_MAP[] = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0X80,0X90};  

และค่าคงที่สำหรับการเลือกว่าจะให้หลักใดติดสว่างก็ใช้วิธีคิดแบบเดียวกันเพียงแต่คราวนี้เราต้องส่ง logic 1 ออกไปยังตำแหน่งที่เราต้องการให้มันติดสว่าง ซึ่งจะมีค่าดังต่อไปนี้


 /* Byte maps to select digit 1 to 4 */  
 const byte SEGMENT_SELECT[] = {0xF1,0xF2,0xF4,0xF8};  

เราเลือกประกาศเป็นค่าคงที่โดยใช้ key word เป็น const เพื่อบอกให้ compiler รู้ว่าค่าใน array เหล่านี้จะไม่มีการเปลี่ยนแปลงค่า ดังนั้น compiler สามารถเก็บค่าเหล่านี้ไว้ใน Flash memory ได้ ทำให้ประหยัด RAM ไปด้วยครับ

               จากนั้นเราก็มาเขียนฟังก์ชั่นที่จะส่งค่าเหล่านี้ออกไปแสดงบน 7-segment แต่ละหลักได้โดยอาศัย shiftOut() ที่ Pinguino มีเตรียมไว้ให้ใช้อยู่แล้ว ซึ่งจะได้เป็นฟังก์ชั่นดังต่อไปนี้ครับ


1:  /* Wite a decimal number between 0 and 9 to one of the 4 digits of the display */  
2:  void WriteNumberToSegment(byte Segment, byte Value)  
3:  {  
4:    digitalWrite(LATCH_DIO,LOW);   
5:    shiftOut(DATA_DIO, CLK_DIO, MSBFIRST, SEGMENT_MAP[Value]);  
6:    shiftOut(DATA_DIO, CLK_DIO, MSBFIRST, SEGMENT_SELECT[Segment] );  
7:    digitalWrite(LATCH_DIO,HIGH);    
8:  }  
             
               และเพื่อให้การเขียนโค้ดง่ายยิ่งขึ้นเราก็จะมีฟังก์ชั่นที่ช่วยแยกตัวเลขที่นับได้ออกเป็นหลักหน่วย หลักสิบ หลักร้อย และหลักพัน เพื่อแสดงผล โดยอาศัยการหารกับหลักนั้นๆ และการหารที่เก็บเฉพาะเศษที่เหลือเท่านั้น(modulus, %) ซึ่งจะได้เป็นฟังก์ชั่นดังต่อไปนี้ครับ


1:  /* Write a decimal number between 0 and 9999 to the display */  
2:  void WriteNumber(int Number)  
3:  {  
4:    WriteNumberToSegment(0 , Number / 1000);  
5:    WriteNumberToSegment(1 , (Number / 100) % 10);  
6:    WriteNumberToSegment(2 , (Number / 10) % 10);  
7:    WriteNumberToSegment(3 , Number % 10);  
8:  }  

               คราวนี้โค้ดตัวอย่างของเราจะทำการแสดงตัวเลขนับค่าเพิ่มขึ้นทุกๆ 500 ms และเราจะใช้ฟังก์ชั่น millis() มาช่วยในการจับเวลาที่จะเพิ่มค่าขึ้น ดังนั้นเราต้องการตัวแปรเพิ่มเติมอีกเพื่อเก็บค่าเวลา ณ ปัจจุบันและค่าเวลาที่ผ่านมา กับตัวแปรไว้นับเลข โดยเราจะประกาศตัวแปรดังนี้


1:  unsigned long Cur_ms_Count;      // Stores the current time in ms  
2:  unsigned long Last_ms_Count;     // Stores the last time in ms the counter was last updated  
3:  unsigned int Count;              // Stores the value that will be displayed  

ในฟังก์ชั่น setup() เราก็กำหนดให้พินที่ควบคุม 74HC595 ที่เรา define ไว้ให้เป็นเอ้าต์พุต และกำหนดค่าเริ่มต้นให้แก่ตัวแปรจับเวลาดังนี้ครับ


1:  void setup() {  
2:    pinMode(25,INPUT);    //turn off buzzer first  
3:   /* Set DIO pins to outputs */  
4:   pinMode(LATCH_DIO,OUTPUT);  
5:   pinMode(CLK_DIO,OUTPUT);  
6:   pinMode(DATA_DIO,OUTPUT);    
7:   /* Initiliase the registers used to store the current time and count */  
8:   Cur_ms_Count = millis();  
9:   Last_ms_Count = 0;  
10:   Count = 0;    
11:  }  

สุดท้ายในฟังก์ชั่น loop() เราก็เพียงแต่คอยเพิ่มค่าทุกๆ 500 ms แล้วเรียกฟังก์ชั่นช่วยเหลือเพื่อแสดงตัวเลขออกไปเท่านั้นเองครับ โดยโค้ดตัวเต็มจะเป็นดังนี้นะครับ


/*-----------------------------------------------------
Author:  --<Ekkachai Muangrodpai>
Date: 2016-08-12
Description: Display and update a number on 7-Segment 
      every 500 ms.
-----------------------------------------------------*/
/* Define shift register pins used for seven segment display */
#define LATCH_DIO     24
#define CLK_DIO       16
#define DATA_DIO      5
 
/* Segment byte maps for numbers 0 to 9 */
const byte SEGMENT_MAP[] = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0X80,0X90};
/* Byte maps to select digit 1 to 4 */
const byte SEGMENT_SELECT[] = {0xF1,0xF2,0xF4,0xF8};

unsigned long Cur_ms_Count;  // Stores the current time in ms
unsigned long Last_ms_Count;  // Stores the last time in ms the counter was last updated
unsigned int  Count;   // Stores the value that will be displayed

/* Wite a decimal number between 0 and 9 to one of the 4 digits of the display */
void WriteNumberToSegment(byte Segment, byte Value)
{
  digitalWrite(LATCH_DIO,LOW); 
  shiftOut(DATA_DIO, CLK_DIO, MSBFIRST, SEGMENT_MAP[Value]);
  shiftOut(DATA_DIO, CLK_DIO, MSBFIRST, SEGMENT_SELECT[Segment] );
  digitalWrite(LATCH_DIO,HIGH);    
}

/* Write a decimal number between 0 and 9999 to the display */
void WriteNumber(int Number)
{
  WriteNumberToSegment(0 , Number / 1000);
  WriteNumberToSegment(1 , (Number / 100) % 10);
  WriteNumberToSegment(2 , (Number / 10) % 10);
  WriteNumberToSegment(3 , Number % 10);
}
void setup() {
    pinMode(25,INPUT);        //turn off buzzer first
   
  /* Set DIO pins to outputs */
  pinMode(LATCH_DIO,OUTPUT);
  pinMode(CLK_DIO,OUTPUT);
  pinMode(DATA_DIO,OUTPUT); 
  
  /* Initiliase the registers used to store the current time and count */
  Cur_ms_Count = millis();
  Last_ms_Count = 0;
  Count = 0;    
}

void loop() {   
  /* Get how much time has passed in milliseconds */
  Cur_ms_Count = millis();
  
  /* If 100ms has passed then add one to the counter */
  if(Cur_ms_Count - Last_ms_Count > 500)
  {
    Last_ms_Count = Cur_ms_Count;
    
    if(Count < 9999)
    {
      Count++;
    } else
    {
      Count = 0;
    }
  }
  
  /* Update the display with the current counter value */
  WriteNumber(Count);  
}




วันอังคารที่ 2 สิงหาคม พ.ศ. 2559

Pinguino กับ LCD Keys pad shield V1.2 (another shield)


              ในบทความก่อนหน้านี้ผมได้เขียนถึงการใช้บอร์ด Pinguino 8 เชื่อมต่อกับ LCD key pad shield, อันนี้ครับ
ซึ่งหลังเขียนเสร็จแล้วผมก็นึกขึ้นมาได้ว่ายังมี LCD key pad shield อยู่อีกอันหนึ่ง( ยี่ห้อ ElecFreaks , shield สีขาวในรูปด้านบน )ซึ่งแตกต่างจากอันแรกตรงที่ใช้ปุ่มกดแบบจอยสติ้ก 5 ทิศทางแทน แต่ยังคงเชื่อมต่อกับไมโครคอนโทรลเลอร์ที่ขา A0 เหมือนเดิมทำให้สามารถใช้โค้ดเดิมได้ และที่เพิ่มขึ้นมาอีกอันก็คือตัว rotary encoder ที่ถ้าดูผิวเผินแล้วเหมือนตัวโวลุ่มเลย โดยเราสามารถหมุนได้ทั้งสองทิศทางซึ่งจะให้เอ้าพุตออกมาสองแชลแนล และมีพัลล์เหลื่อมกันดังแสดงในรูปที่ 2 นอกจากนี้ยังสามารถกดลงคล้ายกับการกดปุ่ม enter ได้อีกด้วย โดยในบทความนี้จะมุ่งเน้นที่การเขียนโค้ดเพิ่อตรวจจับการหมุนหรือเปลี่ยนตำแหน่งของ encoder โดยอาศัยอินเตอร์รับออนเชนต์( interrupt on change ) และมีแก้ไขค่าคงที่ของ keys ต่างๆเพื่อรองรับการกดปุ่มของ encoder ที่เพิ่มเติมขึ้นมา โดยผู้อ่านสามารถหาข้อมูลเพิ่มเติมเกี่ยวกับ shield ตัวนี้ได้จากลิ้งค์ต่อไปนี้ ซึ่งจะมี schematic, datasheet, และโค้ดตัวอย่างของ Arduino ที่เราสามารถนำมาใช้ได้กับ Pinguino ของเรา
รูปที่ 2 เอ้าพุตของ rotary encoder

วิธีการอ่านค่าของ rotary encoder นั้นสามารถหาอ่านเพิ่มเติมได้จากฟอร์รั่มของ Arduino เช่นลิ้งค์ต่อไปนี้

หรือลิ้งค์อันนี้ก็ให้ข้อมูลดีครับและใช้ C18 ในการเขียนโค้ดด้วย

จาก schematic ที่สามารถโหลดได้จากลิ้งค์แรกนั้นจะเห็นว่าเอ้าพุตของ rotary encoder นั้นจะต่ออยู่กับ pin 2 และ 3 ของ Arduino ซึ่งทั้งสองพินนี้นั้นสามารถ config ให้เป็น external interrupt และสามารถเลือกได้ว่าจะให้เกิด interrupt เมื่อเกิดสัญญานขอบขาขึ้นหรือขอบขาลง คราวนี้เมื่อผมจะใช้บอร์ด Pinguino 8 มาแทน Arduino พอเช็คขาที่ตำแหน่งเดียวกันนี้พบว่าบอร์ด Pinguino 8 ที่ตำแหน่ง D2 กับ D3 นี้ไม่รองรับ external interrupt ทำให้ผมต้องมาทำการโมดิฟายตัว shield โดยบัดกรีสายจากตำแหน่ง D2 กับ D3 ไปที่ตำแหน่ง D12 และ D13 ตามลำดับดังแสดงในรูปที่ 3 ครับ

รูปที่ 3 บัดกรีสายจาก D2, D3 ไป D12, D13

โดยที่ตำแหน่งใหม่นี้จะเป็นพินหมายเลข 0 และ 1 บนบอร์ด Pinguino 8 ดังแสดงในรูปที่ 4 ซึ้่งทั้งสองพินนี้รองรับ interrupt on change ตามที่เราต้องการ
รูปที่ 4 หมายเลขพินบน Pinguino 8
               เมื่อ hardware ของเราพร้อมแล้วทีนี้ก็มาถึงขั้นตอนการเขียนโค้ด จากในรูปที่ 2 เมื่อพิจารณาให้ดีจะเห็นว่าในจังหวะที่พัลล์เอ้าพุตแชลแนล A ของ rotary encoder เปลี่ยนลอจิกจาก HIGH เป็น LOW ( Falling Edge ) แล้วถ้าเราอ่านค่าของเอ้าพุตแชลแนล B ได้ค่าเป็น HIGH นั่นแสดงว่า rotary encoder ถูกหมุนไปในทิศทางตามเข็มนาฬิกา ( Clockwise ) เราก็สามาถเพิ่มค่าในตัวแปรที่เราเอาไว้เก็บค่าการหมุนได้ 
               ในทางตรงกันข้ามหากจังหวะที่เอ้าพุตแชลแนล A ของ rotary encoder เปลี่ยนลอจิกจาก HIGH เป็น LOW ( Falling Edge ) แล้วถ้าเราอ่านค่าของเอ้าพุตแชลแนล B ได้ค่าเป็น LOW นั่นแสดงว่า rotary encoder ถูกหมุนไปในทิศทางทวนเข็มนาฬิกา ( Counter-Clockwise ) เราก็สามาถบดค่าในตัวแปรที่เราเอาไว้เก็บค่าการหมุนได้ 
               เมื่อเรารู้แนวคิดในการเขียนโค้ดแล้วเราก็สามารถเริ่มเขียนได้โดยเริ่มจากการ define ชื่อขาของ rotary encoder เพื่อให้ง่ายในการอ่านและเขียนโค้ด และประกาศตัวแปรที่เอาไว้เก็บค่าการหมุน พร้อมทั้งตัวแปรที่จำเป็นดังนี้

1:  #define Encoder_A  0  
2:  #define Encoder_B  1  
3:  volatile int Encoder_number=0;  
4:  volatile u8 state=0;  

จากนั้นในฟังก์ชัน setup() เราก็ config ให้ขา encoder เป็น input ซะ แต่อย่าลืมที่ตำแหน่ง D2 กับ D3 ของ shield นั้นเมื่อเสียบลงบนบอร์ด Pinguino 8 แล้วจะเป็นพินหมายเลข 25 กับ 26 ( ดูได้จากรูปที่ 4 ) ซึ่งโดย default ของตัวไมโครคอนโทรลเลอร์(PIC18F45K50)เองหลังจาก power on or reset ขึ้นมามันจะเป็น output ซึ่งจะทำให้ feature อินเตอร์รัพที่ขา 0 กับ 1 ไม่ทำงานดังนั้นเราจำเป็นต้อง config พิน 25 กับ 26 ให้เป็น input (high impedance) ด้วย interrupt on change ถึงจะทำงานได้ถูกต้อง (หรือไม่งั้นก็ต้องตัดขา D2 กับ D3 ของ shield ทิ้งซะก่อน) จากนั้นจึงจะ enable ความสามารถ Interrupt On Change บน pin 0 โดยให้เกิด interrupt ทุกๆขอบขาลง ( INT_FALLING_EDGE ) โดยเมื่อดักจับขอบขาลงได้ให้กระโดดไปทำงานที่ฟังก์ชั่นชื่อ Encode() ดังตัวอย่างโค้ดต่อไปนี้ครับ


1: //make the pin 2 and 3(which is pin 25, and 26 on Pinguino 8) of LCD keypad shield as input  
2: //so that the pin 0 and 1 of Pinguino 8 that we use for interrupt on change can work correctly  
3:    pinMode(25, INPUT);      
4:    pinMode(26, INPUT);  

5:    pinMode(Encoder_A, INPUT);   
6:    pinMode(Encoder_B, INPUT);   
7:    digitalWrite(Encoder_A, HIGH);  
8:    digitalWrite(Encoder_B, HIGH);  

9:    OnChangePin0(Encode, INT_FALLING_EDGE);  

ในส่วนของฟังก์ชั่น Encode() นั้นเราก็เพียงอ่านค่าของ Encoder_B หากอ่านได้เป็น 1 (HIGH) ก็ให้เพิ่มค่าตัวแปร แต่หากอ่านค่าได้เป็น 0 (LOW) ก็ลดค่าตัวแปรลง จากนั้นจึงบอกให้ฟังก์ชัน loop รู้ว่า rotary encoder มีการหมุน( เปลี่ยนแปลงค่า ) โดยการเซ็ทให้ตัวแปร state เป็น 1 เพื่อที่ในฟังก์ชั่น loop จะได้อัพเดตค่าบนจอ LCD ต่อไป ตัวอย่างโค้ดก็จะเป็นตามนี้นะครับ


1:  void Encode(){  
2:    if(digitalRead(Encoder_B))  
3:       {  
4:         Encoder_number++;  
5:       }  
6:      else  
7:       {   
8:        Encoder_number--;  
9:       }     
10:       state=1;  
11:  }  

และในส่วนของฟังก์ชั่น loop() เราก็จะเพิ่มโค้ดเพื่ออัพเดตค่าของ Encoder_number บนจอ LCD โดยจะทำการอัพเดตก็ต่อเมื่อมีการหมุน rotary encoder เท่านั้น ดังโค้ดตัวอย่างต่อไปนี้ครับ


1:  if(state==1)  
2:   {   
3:    lcd.clear();  
4:    lcd.setCursor(9,1);      // move cursor to second line "1" and 9 spaces over   
5:    lcd.printf("%d",Encoder_number);   
6:    lcd.setCursor(0,0);      // move cursor to second line "1" and 9 spaces over   
7:    lcd.printf("Push the buttons"); // print a simple message   
8:    state=0;  
9:   }   

สุดท้ายเราก็จะมาแก้ไขค่าการเปรียบเทียบค่าที่อ่านได้จาก ADC จากตัวอย่างในบทความเกี่ยวกับ LCD keys pad shield ที่ผ่านมา โดยแก้ไขค่าเป็นดังนี้ครับ


1:  if (adc_key_in > 1000) return btnNONE; // We make this the 1st option for speed reasons since it will be the most likely result  
2:   // For V1.1 us this threshold  
3:   if (adc_key_in < 50)  return btnLEFT;  
4:   if (adc_key_in < 150) return btnUP;  
5:   if (adc_key_in < 250) return btnRIGHT;  
6:   if (adc_key_in < 450) return btnSELECT;  
7:   if (adc_key_in < 700) return btnDOWN;  
8:   if (adc_key_in < 850) return btnEncodeOK;   

และต้องเพิ่มสเตรทในฟังก์ชั่น loop ขึ้นอีกอันหนึ่งด้วย สำหรับปุ่ม Encode OK ซึ่งโค้ดตัวเต็มก็จะเป็นดังนี้ครับ
1:  /*-----------------------------------------------------  
2:  Author: --<Ekkachai Muangrodpai>  
3:  www.picgetstart.blogspot.com  
4:  Date: 2016-03-18  
5:  Board:  Pinguino8 by Jimmy + LCD Keypads Shield V.1  
6:  Description:  
7:  -Display a message on LCD Keypads Shield, and also read a keys through analog AN0.  
8:  -At the same time, display the second time too.  
9:   * LCD RS pin to digital pin 5  
10:   * LCD E pin to digital pin 4  
11:   * LCD D4 pin to digital pin 24  
12:   * LCD D5 pin to digital pin 18  
13:   * LCD D6 pin to digital pin 17  
14:   * LCD D7 pin to digital pin 16  
15:   * LCD R/W pin to ground  
16:   note:  
17:   - don't use lcd.print() and lcd.printf() in the same program.  
18:  -----------------------------------------------------*/  
19:  #define BACK_LIGHT  2    //LCD back light control by pin2  
20:  // define some values used by the panel and buttons  
21:  int lcd_key   = 0;  
22:  int adc_key_in = 0;  
23:  #define btnRIGHT 0  
24:  #define btnUP   1  
25:  #define btnDOWN  2  
26:  #define btnLEFT  3  
27:  #define btnSELECT 4  
28:  #define btnNONE  5  
29:  #define btnEncodeOK 6  
30:  #define Encoder_A  0  
31:  #define Encoder_B  1  
32:  volatile int Encoder_number=0;  
33:  volatile u8 state=0;  
34:  // read the buttons  
35:  int read_LCD_buttons()  
36:  {  
37:   adc_key_in = analogRead(0);   // read the value from the sensor   
38:  // my buttons when read are centered at these valies: 0, 144, 329, 504, 741  
39:   // we add approx 50 to those values and check to see if we are close  
40:   if (adc_key_in > 1000) return btnNONE; // We make this the 1st option for speed reasons since it will be the most likely result  
41:   // For V1.1 us this threshold  
42:   if (adc_key_in < 50)  return btnLEFT;  
43:   if (adc_key_in < 150) return btnUP;  
44:   if (adc_key_in < 250) return btnRIGHT;  
45:   if (adc_key_in < 450) return btnSELECT;  
46:   if (adc_key_in < 700) return btnDOWN;  
47:   if (adc_key_in < 850) return btnEncodeOK;   
48:   return btnNONE; // when all others fail, return this...  
49:  }  
50:  void Encode(){  
51:    if(digitalRead(Encoder_B))  
52:       {  
53:         Encoder_number++;  
54:       }  
55:      else  
56:       {   
57:        Encoder_number--;  
58:       }     
59:       state=1;  
60:  }  
61:  void setup( void) {  
62:    // put your setup code here, to run once:  
63:    pinMode(BACK_LIGHT, OUTPUT);  
64:    digitalWrite(BACK_LIGHT, HIGH);  
65:    // initialize the library with the numbers of the interface pins    
66:    lcd.pins(5, 4, 24, 18, 17, 16, 0, 0, 0, 0); // RS, E, D4 ~ D8    
67:    // set up the LCD's number of columns and rows:   
68:    lcd.begin(16, 2);  
69:    // Print a message to the LCD.  
70:    lcd.clear();  
71:    lcd.setCursor(0,0);  
72:    lcd.printf("Push the buttons"); // print a simple message  
73:    //make the pin 2 and 3(which is pin 25, and 26 on Pinguino 8) of LCD keypad shield as input  
74:    //so that the pin 0 and 1 of Pinguino 8 that we use for interrupt on change can work correctly  
75:    pinMode(25, INPUT);      
76:    pinMode(26, INPUT);  
77:    pinMode(Encoder_A, INPUT);   
78:    pinMode(Encoder_B, INPUT);   
79:    digitalWrite(Encoder_A, HIGH);  
80:    digitalWrite(Encoder_B, HIGH);  
81:    OnChangePin0(Encode, INT_FALLING_EDGE);  
82:  }  
83:  void loop( void ) {  
84:   if(state==1)  
85:   {   
86:    lcd.clear();  
87:    lcd.setCursor(9,1);      // move cursor to second line "1" and 9 spaces over   
88:    lcd.printf("%d",Encoder_number);   
89:    lcd.setCursor(0,0);      // move cursor to second line "1" and 9 spaces over   
90:    lcd.printf("Push the buttons"); // print a simple message   
91:    state=0;  
92:   }   
93:   lcd.setCursor(0,1);      // move to the begining of the second line  
94:   lcd_key = read_LCD_buttons(); // read the buttons  
95:   switch (lcd_key)        // depending on which button was pushed, we perform an action  
96:   {  
97:    case btnRIGHT:  
98:     {  
99:       lcd.printf("RIGHT  ");  
100:       break;  
101:     }  
102:    case btnLEFT:  
103:     {  
104:       lcd.printf("LEFT   ");  
105:       break;  
106:     }  
107:    case btnUP:  
108:     {  
109:       lcd.printf("UP    ");  
110:       break;  
111:     }  
112:    case btnDOWN:  
113:     {  
114:       lcd.printf("DOWN  ");  
115:       break;  
116:     }  
117:    case btnSELECT:  
118:     {  
119:       lcd.printf("SELECT  ");  
120:       break;  
121:     }  
122:    case btnNONE:  
123:     {  
124:       lcd.printf("NONE  ");  
125:       break;  
126:     }  
127:     case btnEncodeOK:  
128:     {  
129:       lcd.printf("EncdOK  ");  
130:       break;  
131:     }  
132:   }  
133:  }  

และข้างล่างนี้คือวิดีโอผลการทำงานของ Pinguino 8 กับ LCD key pad shield V1.2 ครับ