Main Menu
Menu

Show posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Show posts Menu

Messages - top

#17

สวัสดีครับพี่ๆทุกท่าน

คือผม ต้องการที่จะแสดงรูปภาพบนหน้าจอ GLCD128x64 ทำอย่างไรดีครับ

ควบคุมผ่าน IC 74HC595 ครับ

แต่ถ้าควบคุม I/O Port ธรรมดา สามารถแสดงรูปภาพได้ครับ

ขอคำแนะนำด้วยครับ

     ขอบคุณมากครับ

http://320volt.com/en/ccs-c-74hc595-cd4094-128x64-4x20-lcd-kullanimi/

ด้านล่าง คือ Code ที่สามารถแสดงรูปภาพได้ครับ

void printf_bmp(char select)
{
   unsigned int16 i,j;
   for(i=0;i<8;i++)//8
   {
         output_low(GLCD_DI);                        // Set for instruction
         glcd_writeByte(GLCD_LEFT, 0x40);    // Set horizontal address to 0
         glcd_writeByte(GLCD_RIGHT,0x40);
         glcd_writeByte(GLCD_LEFT, i | 0xb8);// Set page address
         glcd_writeByte(GLCD_RIGHT, i | 0xb8);
         output_high(GLCD_DI);   
         
         // Loop through the horizontal sections
         for(j=0;j<64;j++)
         {
            if(select==1)
            {
               glcd_writeByte(GLCD_LEFT,img[j+(i*128)]);      // Turn pixels on or off
            } 
         }
         for(j=64;j<128;j++)
         {
            if(select==1)
            {
               glcd_writeByte(GLCD_RIGHT,img[j+(i*128)]);      // Turn pixels on or off
            }
         }       
   }
}





#18
   
   สวัสดีปีใหม่ไทยครับ

  วันสงกรานต์ปีนี้ หลายๆคนก็ได้กลับบ้านไปหาครอบครัวกัน

  เล่นน้ำกันสนุกสนาน แต่ผมตรงข้ามครับไม่ได้กลับบ้าน ไม่ชอบเล่นน้ำ

นอนเล่นอยู่ที่ห้อง นั่งทดลองไป ว่างๆก็พาครอบครัวไปเทียวห้าง

วันสงกรานต์ในปีนี้ คุณได้สังเกตุเห็นอะไรบ้างครับ

ผมสังเกตุเห็น รอยยิ้มและเสียงหัวเราะ คนไทยมีความมากขึ้น

วันสงกรานต์เป็นวันรวมผลของเด็กเวร  ซิ่งรถยกล้อกันสนุก

เมื่อวานเห็น ซิ่งรถจนเกิดอุบัติเหตุ ก็เจ็บกันไป

วันหยุดยาวแบบนี้ ถนนหลายเส้นทาง รถไม่ค่อยมีดีจังเลยครับ

สุดท้ายนี้ขอให้ทุกคน มีความสุข ในวันสงกรานต์ปีนี้ ครับ

   เดินทาง โดยสวัสดิภาพ นะครับ



#19
Microchip PIC / Re: Encoder 1000/r + PIC
April 14, 2014, 05:46:32 AM
    สวัสดีครับพี่ๆทุกท่าน

  จากที่ได้ทำการทดลองและศึกษา การอ่านค่า Encoder กับ การควบคุมแบบ PID

  วันนี้ก็ประสบควาทสำเสรึจในระดับหนึง สามารถอ่านค่า Encoder  และ ควบคุมแบบ PID ได้แล้ว

  แต่ยังติดปัญหาเรื่อง ความถูกต้องในแต่ละครั้งที่อ่านค่า  เช่น ค่า set point = 30,000 Pulse

ในบางครั้ง อ่านได้ 30,001 หรือไม่ก็  29,999

ขอถามผู้รู้ การควบคุมแบบ PID  ดังนี้ครับ

  1 : ผมต้องแก้ไขยังไงดีครับ จาก โปรแกรมด้านล่าง

  2 : หากผมต้องการให้ โปรแกรม เพิ่มและลดค่า PWM เอง โดยเช็กจากที่ผ่านเวลา ผมต้องทำยังไงดีครับ

ขอขอบคุณมากครับ

code :

/*
     SERVO MOTOR : YASKAWA
           TYPE  : UGTMEM-02SA2XE
            P/N  : UTOPI-100SC
            S/N  : 626180-1
*/
//.................................................................//
#include <18F4431.h>
#fuses INTRC_IO, NOWDT, NOPROTECT, NOBROWNOUT, PUT, NOLVP
#use delay(clock=8000000)

#include "lcd420.c"
#use fast_io(B)
#define Mode PIN_c6
#define led PIN_c5
#define POWER_PWM_PERIOD 1999  // 1 KHz pwm freq with 8 MHz osc.
#define Encoder 2000 // Pulse Resolution 2000P/R
unsigned long count1;
int1 r,p1;
long position,Angle,over,over1;

int8  count,nghin, tram, chuc, donvi;
long feedback,error,pre_error,integral,derivative; //signed int16
long control;
long temp, setpoint=30000, feed;
float Kp, Ki, Kd, P, I, D, dt, value;

//#INT_RTCC
//void RTCC_IRS()

#INT_TIMER1                                                                                             
void isr_timer1(void)                                                         
{                                                                                   
   set_timer1(59500);//60535   

++count;
if(count>10)
{
    count=0;
        if(setpoint>=feedback) 
       {
        //  feedback=Position;
          error=setpoint-feedback;
          control=(int16)(P+I+D);
         
       }else  if(setpoint<feedback)
          {
            over=feedback-setpoint;
          //  feedback=setpoint-over;
            over1=setpoint-over;
            error=setpoint-over1;
            control=(int16)(P+I+D);
          }
    feedback=Position;
   // error=setpoint-feedback;
    integral+=error;            // Accumulated sum of error
    derivative=error-pre_error; // Derivative of error
    if((error<2)&&(error>0))
        {
         Kp = 0.0;
         Kd = 0.0;
         Ki = 0.0;
         control = control;     // Don't use PID
           }
      else
       {
         Kp = 0.65; //8
         Ki = 0.37; //5
         Kd = 0.0001; // Assign value for Kp, Ki, Kd
           
         P=Kp*error;
         I=Ki*integral*dt;
         D=Kd*derivative;
       //  control=(int16)(P+I+D);

       if(setpoint!=feedback)
         {
         if(control > 1023)
          { 
            control = 1023;   // Limit the maximum value control at 90%
          }
         
         if(control < 85)
            {
            control = 85;   // Limit the minimum value control at 10%
            }
         }
         
}
       //  set_pwm1_duty(control);
         pre_error = error;         // Update error
    }
  }
//.............................................................................//

void main(void)
{

    dt =0.0001;  // Sample time = 1ms = 100us(overflow time)*10 (count) 0.001
  control = 0;
 
  derivative = 0;
  integral = 0;
  error = 0;
  Kp = 0.0;
  Kd = 0.0;
  Ki = 0.0;

   set_tris_b(0x00);
   set_tris_a(0x3C);
   
   setup_ccp1(CCP_PWM_PLUS_1); // Configure CCP1 as a PWM
   setup_ccp2(CCP_PWM_PLUS_2); // Configure CCP2 as a PWM

   setup_timer_2(T2_DIV_BY_16,255,1);
   setup_timer_5(T5_INTERNAL|T5_DIV_BY_1);
   setup_QEI(QEI_FILTER_ENABLE_INDX
            |QEI_VELOCITY_MODE_ENABLED
            |QEI_VELOCITY_PULSE_DIV_16);
             
  enable_interrupts(int_timer1);             
   setup_timer_1(T1_INTERNAL|T1_DIV_BY_4);                                       
   set_timer1(59500);//60535
  // setup_timer_0(RTCC_DIV_2);
// set_timer0(6);                       // T_overflow = 2*(256-6)*0.2us = 100us
// enable_interrupts(INT_RTCC);         // enable interrupts Timer0
  enable_interrupts(GLOBAL);
 
   lcd_init();  // Always call this first.
   output_high(PIN_D0);
   output_low (PIN_D2);
lcd_gotoxy(1,1);//"----------------"                 //
   printf(lcd_putc," Rotary Encoder ");
   lcd_gotoxy(1,2);
   printf(lcd_putc,"----------------");
   output_high(led);
   delay_ms(600);
//  output_low(alive);

while(true)
   {
      Position=qei_get_count(QEI_GET_POSITION_COUNT);     
      COUNT=qei_get_count(QEI_GET_VELOCITY_COUNT);     
      Angle=(Position/Encoder);
      if(input(Mode)==0&&r==0)
      {
         p1=~p1;
         r=1;
      }else if(input(Mode)==1)r=0;
     
     
      if(setpoint<feedback)
      {
         set_pwm1_duty(control); 
         set_pwm2_duty(0);
         
      }else if(setpoint>feedback)
        {
           set_pwm1_duty(0); 
           set_pwm2_duty(control);
        }else if(setpoint==feedback)
          {
             set_pwm1_duty(0); 
             set_pwm2_duty(0);
              control=0;
              Kp = 0.0;
              Kd = 0.0;
              Ki = 0.0;
          }
         
    lcd_gotoxy(1,1);//"----------------"                  //
      printf(lcd_putc,"PID: %u:%u:%u  ",P,I,D);
      lcd_gotoxy(1,2);
      printf(lcd_putc,"Er : %lu        ",error);
     
      lcd_gotoxy(1,3);//"--------------------");                 //
      printf(lcd_putc,"PWM: %ld       ",control);
      lcd_gotoxy(1,4);
      printf(lcd_putc,"P :  %lu       ",Position);
                              //allow LCD some responce time
   }//while loop         
} // end mai


#20
Microchip PIC / Re: Encoder 1000/r + PIC
March 02, 2014, 03:03:13 PM
สวัดดีครับพี่ๆทุกท่าน

      จากที่ได้ทำตามคำแนะนำของหลายๆท่าน ก็ประสบความสำเร็จในระดับนึง

แต่ปัญหาใหม่ก็มา   คือว่า  ผมต้องการให้แสดงค่าระหว่าง   - 2,000,000,000 ถึง +2,000,000,000  ได้อย่างไร  จาก code ด้านล่าง  :-[

ผมจะต้องประกาศตัวแปรอย่างไรดีครับ และผมต้องการวัดรอบ Encoder (RPM)  ผมจะต้องเขียนย่างไรครับ 

ขอคำแนะนำด้วยครับ  :-\
     
        ขอบคุณครับ
#include <18F2431.H>
#fuses hs, NOWDT, NOBROWNOUT, PUT, NOLVP,NOMCLR
#use delay(clock = 20000000)

#USE rs232(bAUD=9600,XMIT=PIN_C6, RCV=pin_c7, BITS=8,errors)

#include "lcd420.c"

//*********************DEFINITIONS**************
#define Tare PIN_b0
#define Print PIN_B1
#define Alive PIN_B7


// note do note use PINS D0-D3 and Pins B4-B6 as they are reserved for ETAngleMeter-LCD driver

//*********************Variables************************************
unsigned long count,timer;

//signed
long position;
float angle;
INT DIRF,ext;
   
//=========================




void main()
{
   
   set_tris_b(0x03); // B0 - B1 as inputs
   set_tris_a(0x3C); // RA2,Ra3,RA4 as input 
   setup_timer_5(T5_INTERNAL|T5_DIV_BY_1); // so timer 5 should roll over every 0.07 sec based on (4MHZ / 4 x 8)
   setup_QEI(QEI_FILTER_ENABLE_INDX|QEI_VELOCITY_MODE_ENABLED|QEI_VELOCITY_PULSE_DIV_64); //QEI_FILTER_ENABLE_INDX,QEI_MODE_X4_RESET_WITH_INDX
   delay_ms(15);
   count=0; //
   lcd_init();  // Always call this first.
   lcd_gotoxy(1,1);                 //
   printf(lcd_putc,"   Rotary Encoder   ");
   lcd_gotoxy(1,2);
   printf(lcd_putc,"--------------------");
   output_high(Alive);
   delay_ms(600);
   output_low(alive);



while(true)
   {
   
      Position=qei_get_count(QEI_GET_POSITION_COUNT);      //get position
      COUNT=qei_get_count(QEI_GET_VELOCITY_COUNT);      //get time between velocity events
      Angle=Position/(float)4; // convert x4 to degrees
     
      lcd_gotoxy(1,3);//"--------------------");                 //
      printf(lcd_putc,"Angle:  %5.2f        ",angle);
      lcd_gotoxy(1,4);
      printf(lcd_putc,"count:  %ld          ",Position);
      output_toggle(alive);                        //   
      delay_ms(100);                              //allow LCD some responce time

   }//while loop
       
 
} // end main



#21
Microchip PIC / Re: Encoder 1000/r + PIC
January 31, 2014, 09:36:06 AM
   
    ต้องขอขอบคุณทั้งสองท่านมากครับที่ให้คำแนะนำ

  แนวคิดของคุณ  OZUKE  ตามที่ผมเข้าใจ คือ External Interrupt ใช้ในการนับสัญญาณ

  ขาธรรมดาอีกขาหนึ่งไว้เช็คทิศทางหรึอเปล่าครับ ผมไม่เคยใช้ ขอคำแนะนำเพิ่มเติมด้วยครับ

  ส่วนคำแนะนำของคุณ  P_Chusak  ผมได้ไปหาดูแล้วมีหลายเบอร์เหมือนกันที่มี ขา  QEA and QEB

  เช่น http://ett.co.th/product2009/ET-PIC/ET-BASE_dsPIC30F4011.html

" ใจจริงผมอยากทำ ชุดควบคุมมอเตอร์ แบบ PID ครับ "

อันนี้ Code ที่ได้จาก net ครับ ผมเองยังไม่ได้ลองนะ จาก code นี้พอเป็นแนวทางหลายๆคนได้

code : Master
#include <18F4431.h>//master
#use delay(clock=20000000)
#include <LCD_TM.c>       
#fuses HS,NOWDT,PUT,BROWNOUT,NOLVP,PWMPIN,SSP_RC
#use rs232(baud=19200,parity=N,xmit=PIN_C6,rcv=PIN_C7,ERRORS)


#define BUFFER_SIZE 32
#use i2c(MASTER, SDA=PIN_C4, SCL=PIN_C5,FORCE_SW)
#define READ_ADDRESS 0x61
#define WRITE_ADDRESS 0x60
BYTE buffer[BUFFER_SIZE];
BYTE next_in = 0;
BYTE next_out = 0;
char c;


#int_rda
void serial_isr() {
 
   int t;
   


   buffer[next_in]=getc();
   t=next_in;
   next_in=(next_in+1) % BUFFER_SIZE;
   if(next_in==next_out)
     next_in=t;           // Buffer full !!
     
     
}


#define bkbhit (next_in!=next_out)
char bgetc() {
   char c;


   while(!bkbhit) ;
   c=buffer[next_out];
   next_out=(next_out+1) % BUFFER_SIZE;
   return (c);
}


void main(void) {   
char d='0';


lcd_init();   
   
   //QEICON =0b10110100;     //  11000  quad in x4 mode,INDX reset the position counters 
   //DFLTCON = 0b00111011;      //110001 noise filter on QEA, QEB,, 1:2 clock
  //enable_interrupts(INT_SSP);
  enable_interrupts(int_rda);
// enable_interrupts (INT_IC2QEI);
  enable_interrupts(GLOBAL);
do
   {
 
      lcd_gotoxy(2,2);
      if(bkbhit)
       {
          d=bgetc();       
       } 
    printf(lcd_putc,"%c",d); // LCD is empty
   
    lcd_gotoxy(10,2);
    i2c_start();
    i2c_write(WRITE_ADDRESS);
    i2c_write(d);
    i2c_write(d+1);
     i2c_stop();
     
    printf(lcd_putc,"%02x",i2c_write(d));
 
     delay_ms(100);
   }
   while(true);
}

// code : Slave



#include <18F4431.h>//slave
#use delay(clock=20000000)
#include <LCD_TM.c>
#use fast_io(a)       
#fuses HS,NOWDT,PUT,BROWNOUT,NOLVP,PWMPIN,SSP_RC
#use rs232(baud=19200,parity=N,xmit=PIN_C6,rcv=PIN_C7,ERRORS)


#define BUFFER_SIZE 32
#use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C5, address=0x60,FORCE_HW)
BYTE dummy=0x00;
BYTE address=0x00;
BYTE buffer1[0x10];
BYTE incoming, state;
#INT_SSP
void ssp_interupt ()
{


   state = i2c_isr_state();


   if(state < 0x80)                     //Master is sending data
   {
      incoming = i2c_read();
     
      if(state == 1)                     //First received byte is address
         address = incoming;
         
      if(state == 2)                     //Second received byte is data
         buffer1[address] = incoming;
           
   }
   if(state == 0x80)                     //Master is requesting data
   {
      dummy = i2c_read();
      i2c_write(buffer1[address]);
   }
}


BYTE buffer[BUFFER_SIZE];
BYTE next_in = 0;
BYTE next_out = 0;
char c;






#int_rda
void serial_isr() {
 
   int t;
   


   buffer[next_in]=getc();
   t=next_in;
   next_in=(next_in+1) % BUFFER_SIZE;
   if(next_in==next_out)
     next_in=t;           // Buffer full !!   
}


#define bkbhit (next_in!=next_out)
char bgetc() {
   char c;


   while(!bkbhit) ;
   c=buffer[next_out];
   next_out=(next_out+1) % BUFFER_SIZE;
   return (c);
   
}




void main(void) {   
char d;
buffer1=0x00;
lcd_init();   
   
  // QEICON =0b10110100;     //  11000  quad in x4 mode,INDX reset the position counters 
//  DFLTCON = 0b00111011;      //110001 noise filter on QEA, QEB,, 1:2 clock
   enable_interrupts(INT_SSP);
  enable_interrupts(int_rda);
// enable_interrupts (INT_IC2QEI);
  enable_interrupts(GLOBAL);
do
   {
 
      lcd_gotoxy(2,2);
     
      if(bkbhit)
       {
          d=bgetc();       
       } 
    printf(lcd_putc,"%c",d); // LCD is empty
    if(d=='1'){
    output_d(0x0f);
    }
    else
    {
    output_d(0xff);
    }
    lcd_gotoxy(4,2);
    printf(lcd_putc,"%02x",incoming);
    lcd_gotoxy(7,2);
    printf(lcd_putc,"%02x",state);
    lcd_gotoxy(10,2);
    printf(lcd_putc,"%02x",address);// data receive here
    lcd_gotoxy(14,2);
    printf(lcd_putc,"%02x",buffer1[address]);//confused between 35/16    with d="4",34/15, d="3"
     delay_ms(100);
   }
   while(true);
}
#22
Microchip PIC / Encoder 1000/r + PIC
January 30, 2014, 04:44:04 PM
   
          สวัสดีครับพี่ๆทุกท่าน
   
   ผมต้องการนับ Pulse จาก Encoder ที่มีความลเอียด 1000 P/r

ปัญหาคือ ในขณะที่หมุนรอบ Encoder เร็วๆ ( ใช้มือหมุน ) PIC ตรวจจับสัญญาณไม่ทัน จะแก้ไขปัญหายังดีครับ

ถ้ามีวิธีการตรวจจับสัญญาแบบที่ดีกว่านี้ ขอตัวอย่างด้วยนะครับ

ขอคำแนะนำด้วยครับ 

   coder


#include <16F877a.h>
#fuses  HS,NOLVP,NOWDT,NOPROTECT
//#fuses  HSPLL,PLL5,NOLVP,WDT,NOPROTECT
#use delay(clock=20000000)
//#fuses INTRC_IO,PUT,NOWDT,NOPROTECT,NOLVP,NOBROWNOUT     
#include <lcd420.c>

#define CHA1 PIN_C1
#define CHB1 PIN_C0

#define CHA2 PIN_B0
#define CHB2 PIN_B1

unsigned short canalA1,canalB1;
unsigned short canalA2,canalB2;
unsigned short B_libda1=0,B_libda2=0;
unsigned short A_libda1=0,A_libda2=0;
signed int16 qbe_puleoA1=0,qbe_puleoA2=0;
signed int16 angle1=0,angle2=0;

#zero_ram
void main(void)
{
  lcd_init();
  delay_ms(200);
 
  //angle1=0;
  //angle2=0;
  output_high(PIN_D0);
  output_low (PIN_D2);
 
  lcd_gotoxy(1,2);
  printf(lcd_putc,"  Test  Rotary  ");
  lcd_gotoxy(1,3);
  printf(lcd_putc,"     Encoder    ");
  //lcd_gotoxy(1,1);
// printf(lcd_putc,"............... ");
  delay_ms(1000);
 
  while(true)
  {
     canalA1=input_state(CHA1);
     canalB1=input_state(CHB1);
     
   //  canalA2=input_state(CHA2);
  //   canalB2=input_state(CHB2);
     
     if(canalA1==1)
     {
       if(A_libda1==0)
       {
          A_libda1=1;
         
          if(B_libda1==0)
             {
                   if(canalB1==1)
                   {
                     qbe_puleoA1=qbe_puleoA1+1;
                     B_libda1=1;
                   }
                   
                   if(canalB1==0)
                   {
                     qbe_puleoA1=qbe_puleoA1-1;
                     B_libda1=1;
                   }
               
             }
       }
     }else if(canalA1==0)
           {
               if(A_libda1==1)
               {
                  A_libda1=0;
               
                   if(B_libda1==1)
                      {
                            if(canalB1==1)
                            {
                               B_libda1=0;
                            }else if(canalB1==0)
                                     {
                                       B_libda1=0;
                                     }
                   
                     }
               }
     }
/*                     if(canalA2==1)
                       {
                           if(A_libda2==0)
                           {
                              A_libda2=1;
                           
                            if(B_libda2==0)
                               {
                                     if(canalB2==1)
                                     {
                                      qbe_puleoA2=qbe_puleoA2+1;
                                       B_libda2=1;
                                     }
                                     
                                     if(canalB2==0)
                                     {
                                       qbe_puleoA2=qbe_puleoA2-1;
                                       B_libda2=1;
                                     }
               
                               }
       }
     }
                       if(canalA1==0)
                          {
                              if(A_libda2==1)
                              {
                                 A_libda2=0;
                               
                               if(B_libda2==1)
                                  {
                                        if(canalB2==1)
                                        {
                                          B_libda2=0;
                                        }
                                       
                                        if(canalB2==0)
                                        {
                                          B_libda2=0;
                                        }
                                     
                                  }
                            }
                          }
*/                         
                                 angle1=qbe_puleoA1;
                                 angle2=qbe_puleoA2;
                                 
                  lcd_gotoxy(1,1);                 //
                  printf(lcd_putc," Rotary Encoder ");
                  lcd_gotoxy(1,2);
                  printf(lcd_putc,"----------------");
                  lcd_gotoxy(1,3);                 //
                  printf(lcd_putc,"Cha_1 =  %ld    ",angle1);
                  lcd_gotoxy(1,4);
                  printf(lcd_putc,"Cha_2 =  %ld    ",angle2);
  }//while
 
}//main

 



   
#23
    ได้แล้วครับ
ต้องขอขอบคุณ คุณ ph_sarawut มากเลยครับที่ให้คำแนะนำ

ขอบคุณครับ



#24
 
     ต้องขอขอบคุณพี่ๆทั้งสองท่านที่ให้คำแนะนำ

ผมมีแนวคิดที่จะทำไม่รู้ว่าจะได้รึเปล่า คือ ใช้เบอร์ใกล้เคียง มา Program 18f46k80

แต่ถ้าไม่ได้ก็คงต้องเปลียนเบอร์ IC ใช้เบอร์อืนแทน  หรือไม่ก็อาจซื้อ เครื่อง Program ตัวใหม่

ขอบคุณครับ