Electoday 4.0

ไมโครคอนโทรลเลอร์ => ARM Processors => Topic started by: secret07 on February 06, 2013, 05:47:13 pm

Title: ควบคุมตำแหน่งมอเตอร์
Post by: secret07 on February 06, 2013, 05:47:13 pm
มอเตอร์ที่ผมใช้นั้น 6000rpm มีทดเหลือ 10 rpm ตรงปลายเพลา มี encoder 500pulse/rev ติดที่ตูดวัดตัว 6000 rpm นะครับ
เพราะฉะนั้น pulse ใน 1 รอบที่ออกมาจะเท่ากับ pulse = (6000/10)*500 = 300000 pulse / rev ที่ปลายเพลา

ผมใช้ บอร์ด lpc2138 exp ไรเนี้ยซึ่งผมเขียนโค๊ดโดยมี Interrupt uart0 สำคัญสุด
รองลงมาคือ Interrupt Timer1 วัด encoder
รองมาคือ Interrupt Timer0 คอยอัพเดต PWM

หมุนประมาณ 1 รอบ[กะๆเอา] มันโชออกมาประมาณแค่ 340 องศาเอง [แบบยังไม่ใช้ Interrupt Timer0]
ยิ่งพอรวมใช้ Interrupt Timer0 ค่าที่อ่านจาก Encoder จะไม่ทันเลย หมุนไปเป็นรอบยัวัดได้แค่ 10 - 20 องศาเอง

คือมัน Interrupt ไม่ทันอ่ะ จากเดินก็ไม่ค่อยทันอยู่แล้ว ยิ่งมี Interrupt Timer0 เข้ามา ยิ่งอ่านไม่ทันเลย

มันละเอียดเกิ๊นนนนน  จะแก้ไขยังไงดีครับ  :'( :'(
Title: Re: ควบคุมตำแหน่งมอเตอร์
Post by: firmware.c on February 06, 2013, 05:51:46 pm
หา MCU ใหม่ที่มี encoder input hardware
Title: Re: ควบคุมตำแหน่งมอเตอร์
Post by: secret07 on February 06, 2013, 05:55:04 pm
ช่วยแนะนำหน่อยได้ไหมครับว่าตัวไหนอ่า
Title: Re: ควบคุมตำแหน่งมอเตอร์
Post by: secret07 on February 06, 2013, 08:50:15 pm
แล้วมีทางแก้ไหมครับถ้าไม่เปลี่ยน ตัวใหม่
Title: Re: ควบคุมตำแหน่งมอเตอร์
Post by: firmware.c on February 06, 2013, 10:48:17 pm
แก้ยากครับเพราะมันละเอียดมาก แนะนำให้หา mcu ตัวใหม่อย่างที่บอกเอาพวก dsPIC ก็ได้มีโหมดนี้อยู่
Title: Re: ควบคุมตำแหน่งมอเตอร์
Post by: secret07 on February 07, 2013, 06:47:11 am
ขอบคุณสำหรับคำตอบครับผม
Title: Re: ควบคุมตำแหน่งมอเตอร์
Post by: tha on February 07, 2013, 06:19:39 pm
stm32f103 timer ก็มี encoder interface mode ด้วย ผมเห็นใน reference manual RM0008 แต่ยังไม่ได้อ่าน
Title: Re: ควบคุมตำแหน่งมอเตอร์
Post by: firmware.c on February 07, 2013, 06:48:36 pm
ใช่ครับมีเหมือนกัน
Title: Re: ควบคุมตำแหน่งมอเตอร์
Post by: firmware.c on February 07, 2013, 08:04:13 pm
เพิ่งเห็นว่ามี Code มาด้วย Code ใช้ floating point ด้วย แนะนำว่าลองไม่ใช้ดูอาจจะทันก็ได้
Title: Re: ควบคุมตำแหน่งมอเตอร์
Post by: tha on February 08, 2013, 07:41:58 am
ลองดู stm32f3 DSP standard peripherals library ซิครับ มีตัวอย่าง TIM_EncoderMode ด้วยครับ ไม่รู้ใช้ได้หรือเปล่า ผมก็ยังไม่เคยทำ ตัวนี้ ETT มีขายราคาไม่แพง
http://www.st.com/stonline/stappl/resourceSelector/app?page=resourceSelector&doctype=FIRMWARE&SubClassID=1605 (http://www.st.com/stonline/stappl/resourceSelector/app?page=resourceSelector&doctype=FIRMWARE&SubClassID=1605)
Title: Re: ควบคุมตำแหน่งมอเตอร์
Post by: secret07 on February 08, 2013, 04:33:01 pm
ขอบคุณท่าน tha และ firmware.c มากครับที่มาแนะนำ

ในที่สุดก็ได้แล้วครับหลังจากดันทุลังไม่อยากเสียตัง ผมลองปรับ TIMER จาก Interrupt ทุก 1ms เป็น 100 ms
และเปลี่ยน ไม่ใช้ float ตามที่ท่านบอก ก็เห็นผลเลยครับ

ตอนนี้อยากให้มันแสดงผ่าน LCD แทนเลยไปซื้อ LCD 16x2 มาต่อตรงช่อง P1.25 - P1.31 ที่ทาง ETT ทำมาต่อแบบ 4 bit ไรเนี้ยแระ
ตอนนี้หน้าจอไฟสีฟ้าสว่างสวยงามมาก แถวแรกขึ้นเป็นสี่เหลี่ยมขาว ๆ

(http://image.ohozaa.com/i/2c1/4Ta0xa.png)

** ปัญหาคือสั่งออก LCD ยังไงอ่ะครับ **

 :'( :'( :'(
Title: Re: ควบคุมตำแหน่งมอเตอร์
Post by: firmware.c on February 08, 2013, 10:56:34 pm
ยินดีด้วยที่สามารถผ่านปัญหาไปได้ พยายามหลีก floating point ให้ไกลครับ หาก integer ปกติละเอียดไม่พอในกสรคำนวณแนะนำให้ศึกษาเรื่อง fixed point เพิ่มเติม ส่วนเรื่อง LCD 4 bit ตัวอย่างมีมากมายใน google ครับ
Title: Re: ควบคุมตำแหน่งมอเตอร์
Post by: secret07 on February 09, 2013, 11:51:07 am
ไม่ทราบว่าผมเขียนในการสั่งออก LCD ผิดตรงไหนป่าว
คือมันไม่แสดงข้อความตามนั้นเลย
 
Code: [Select]
/***************************************/
/*                 LCD                 */
/* LCD Routines for "ET-ARM7 KIT V1.0" */
/* Character 16x2 4-Bit Mode Interface */
/***************************************/

#include <LPC213x.H>
#include <stdio.h>

/*************************/
/* Define LCD PinIO Mask */
/*************************/
#define  LCD_D4     (1<<28)    // P1.28
#define  LCD_D5     (1<<29)    // P1.29
#define  LCD_D6     (1<<30)    // P1.30
#define  LCD_D7     (1<<31)    // P1.31
#define  LCD_EN     (1<<27)    // P1.27
#define  LCD_RS     (1<<25)    // P1.25
#define  LCD_DATA   (LCD_D4|LCD_D5|LCD_D6|LCD_D7)
#define  LCD_IOALL  (LCD_D4|LCD_D5|LCD_D6|LCD_D7|LCD_EN|LCD_RS)

#define  lcd_rs_set() IOSET1 |= LCD_RS // RS = 1 (Select Instruction)
#define  lcd_rs_clr() IOCLR1 |= LCD_RS // RS = 0 (Select Data)
#define  lcd_en_set() IOSET1 |= LCD_EN // EN = 1 (Enable)
#define  lcd_en_clr() IOCLR1 |= LCD_EN // EN = 0 (Disable)

#define  lcd_clear()          lcd_write_control(0x01) // Clear Display
#define  lcd_cursor_home()    lcd_write_control(0x02) // Set Cursor = 0
#define  lcd_display_on()     lcd_write_control(0x0E) // LCD Display Enable
#define  lcd_display_off()    lcd_write_control(0x08) // LCD Display Disable
#define  lcd_cursor_blink()   lcd_write_control(0x0F) // Set Cursor = Blink
#define  lcd_cursor_on()      lcd_write_control(0x0E) // Enable LCD Cursor
#define  lcd_cursor_off()     lcd_write_control(0x0C) // Disable LCD Cursor
#define  lcd_cursor_left()    lcd_write_control(0x10) // Shift Left Cursor
#define  lcd_cursor_right()   lcd_write_control(0x14) // Shift Right Cursor
#define  lcd_display_sleft()  lcd_write_control(0x18) // Shift Left Display
#define  lcd_display_sright() lcd_write_control(0x1C) // Shift Right Display

/********************/
/* Declare Function */
/********************/
void lcd_init(); // Initial LCD
void lcd_wait(); // Wait Busy LCD Complete
void lcd_out_data4(unsigned char); // Strobe 4-Bit Data to LCD
void lcd_write_byte(unsigned char); // Write 1 Byte Data to LCD
void lcd_write_control(unsigned char); // Write Instruction
void lcd_write_ascii(unsigned char); // Write LCD Display(ASCII)
void goto_cursor(unsigned char); // Set Position Cursor LCD
void lcd_print(unsigned char*); // Print Display to LCD
void delay(unsigned long int); // Delay Function

/*****************/
/* Main Function */
/*****************/
int main(void)

PINSEL2 = 0x00000000;

IODIR1 |= 0xFA000000; // P1.25 - P1.31 = Output
lcd_init();

while(1)
{
      goto_cursor(0x00); // ROW 1     
               //0123456789ABCDEF 
      lcd_print("** My Project **"); 

      goto_cursor(0x40);      // ROW 2
               //0123456789ABCDEF 
      lcd_print("**  TEST LCD  **");  }
}

/**************************/
/* Wait Bysy LCD Complete */
/**************************/
void lcd_wait()
{
int loop=500;  // Busy Delay Time     
while(loop--);  // Busy Loop
}

/****************************/
/* Strobe 4-Bit Data to LCD */
/****************************/
void lcd_out_data4(unsigned char val)
{
IOCLR1 |= (LCD_DATA);   // Reset 4-Bit Pin Data
IOSET1 |= (val<<28);  // DDDD EN,0,RS,0 0000 0000 0000 0000 0000 0000
}

/****************************/
/* Write Data 1 Byte to LCD */
/****************************/
void lcd_write_byte(unsigned char val)

lcd_out_data4((val>>4)&0x0F); // Strobe 4-Bit High-Nibble to LCD
lcd_en_set(); // EN = 1 = Strobe Signal 
lcd_en_clr(); // EN = 0
lcd_wait(); // Wait LCD Execute Complete

lcd_out_data4((val)&0x0F); // Strobe 4-Bit Low-Nibble to LCD
lcd_en_set(); // EN = 1 = Strobe Signal   
lcd_en_clr(); // EN = 0   
lcd_wait(); // Wait LCD Execute Complete
}

/****************************/
/* Write Instruction to LCD */
/****************************/
void lcd_write_control(unsigned char val)
{
lcd_rs_clr(); // RS = 0 = Instruction Select
lcd_write_byte(val); // Strobe Command Byte  
delay(50000);   // Approx. 2mS Delay
}

/****************************/
/* Write Data(ASCII) to LCD */
/****************************/
void lcd_write_ascii(unsigned char c)
{
lcd_rs_set(); // RS = 1 = Data Select
lcd_write_byte(c);     // Strobe 1 Byte to LCD   
}

/*******************************/
/* Initial 4-Bit LCD Interface */
/*******************************/
void lcd_init()
{
lcd_rs_clr(); // RS = 0 = Instruction Select
lcd_en_clr(); // EN = 0 
delay(50000); // wait VDD raise > 4.5V

lcd_write_control(0x33); // Initial (Set DL=1 3 Time, Reset DL=0 1 Time)
lcd_write_control(0x32);
lcd_write_control(0x28);  // Function Set (DL=0 4-Bit,N=1 2 Line,F=0 5X7)
lcd_write_control(0x0C);  // Display on/off Control (Entry Display,Cursor off,Cursor not Blink)
lcd_write_control(0x06);  // Entry Mode Set (I/D=1 Increment,S=0 Cursor Shift)
lcd_write_control(0x01);  // Clear Display  (Clear Display,Set DD RAM Address=0)
}

/***************************/
/* Set LCD Position Cursor */
/***************************/
void goto_cursor(unsigned char i)
{
i |= 0x80; // Set DD-RAM Address Command
lcd_write_control(i); 
}

/************************************/
/* Print Display Data(ASCII) to LCD */
/************************************/
void lcd_print(unsigned char* str)
{
int i;

for (i=0;i<16 && str[i]!=0;i++)  // 16 Character Print
{
lcd_write_ascii(str[i]); // Print Byte to LCD
}
}

/***********************/
/* Delay Time Function */
/*    1-4294967296     */
/***********************/
void delay(unsigned long int count1)
{
while(count1 > 0) {count1--;} // Loop Decrease Counter
}
Title: Re: ควบคุมตำแหน่งมอเตอร์
Post by: secret07 on February 10, 2013, 12:01:12 am
ผมดูของเว็บนี้เป็นตัวอย่างอ่ะ  http://www.thaimicrotron.com/Referrence/LCD/LCD-Module3.htm
ไม่รู้ว่าเซ็ตแล้วมันผิดตรงไหนป่าวหว่า
ช่วยดูโค๊ดข้างบนนี้ให้หน่อยว่าผิดพลาดตรงไหน
Title: Re: ควบคุมตำแหน่งมอเตอร์
Post by: tha on February 10, 2013, 10:09:26 am
ลองดู code stm32 เปรียบเทียบนะครับ อันนี้ผมลองแล้ว
Title: Re: ควบคุมตำแหน่งมอเตอร์
Post by: crywolf on February 10, 2013, 12:31:52 pm
ผิดหลายจุดเลยครับ

เช่น

   lcd_en_set();
   lcd_en_clr();

ซึ่ง lcd_en หลังจาก set แล้ว ควรหน่วงเวลา อย่างน้อย 500 nsec

ผมแนะนำว่า ให้ไปดู Timing Diagram ใน Datasheet ครับ
และจะเขียน Code ยังไงให้ได้สัญญาณตาม Timing Diagram
Title: Re: ควบคุมตำแหน่งมอเตอร์
Post by: secret07 on February 10, 2013, 08:22:14 pm
ขอบคุณคุณ tha อีกครั้ง และคำแนะนำของคุณ crywolf ด้วยครับ

ตอนนี้ก็เวิร์คแล้วครับ สีสันสวยงาม นั่งเล่นสนุกเลย

 ;D ;D ;D