From: Shawn C. <scy...@gm...> - 2008-03-24 02:11:08
|
Hi again, Thanks for the quick response Dave, but I'm still a bit confuse because there is no other code between the calls to the WriteReg16 function. Here's a bit more details: START CODE SEGMENT /*# Set COM mode to 2. This causes the OCR pin to fall when the timer # reaches the value stored in the OCR register and causes the OCR pin # to rise when the counter gets reset to zero. # # Use a divide by 8 prescalar, which gives a 2MHz clock which will # overflow every 32.7 msec, which is suitable for driving R/C servos*/ //Setup timer 1 I2C_IO_WriteReg8( i2cDev, 0x4F, 0xAA ); //REG_IO8("TCCR1A", 0x4F) I2C_IO_WriteReg8( i2cDev, 0x4E, 0x1A ); //REG_IO8("TCCR1B", 0x4E) I2C_IO_WriteReg16( i2cDev, 0x46, 40000 ); //REG_IO16("ICR1", 0x46) I2C_IO_WriteReg16( i2cDev, 0x4C, 0 ); //REG_IO16("TCNT1", 0x4C) //Setup timer 3 I2C_IO_WriteReg8( i2cDev, 0x8B, 0xAA ); //REG_MEM8("TCCR3A", 0x8B) I2C_IO_WriteReg8( i2cDev, 0x8A, 0x1A ); //REG_MEM8("TCCR3B", 0x8A) I2C_IO_WriteReg16( i2cDev, 0x80, 40000 ); //REG_MEM16("ICR3", 0x80) I2C_IO_WriteReg16( i2cDev, 0x88, 0 ); //REG_MEM16("TCNT3", 0x88) //Move servos to home position I2C_IO_WriteReg16( i2cDev, ch1, servo1*2 );//ch1 = Motor 1 I2C_IO_WriteReg16( i2cDev, ch2, servo2*2 );//ch2 = Motor 2 I2C_IO_WriteReg16( i2cDev, ch3, servo3*2 );//ch3 = Motor 3 I2C_IO_WriteReg16( i2cDev, ch5, servo5*2 );//ch5 = Motor 4 //Set DDR registers for ports B and E I2C_IO_SetGPIODir( i2cDev, 1, 0xE0, 0xE0 );//DDRB = 1 ,0xE0=pins 5,6, and 7 are output I2C_IO_SetGPIODir( i2cDev, 4, 0x38, 0x38 );//DDRE = 4 ,0xE0=pins 5,6, and 7 are output //Set slave address to robostix I2cSetSlaveAddress( i2cDev, gI2cAddr, I2C_USE_CRC ); t1=get_time(); I2C_IO_WriteReg16( i2cDev, ch1, servo1*2 );//ch1= 3C t2=get_time(); I2C_IO_WriteReg16( i2cDev, ch2, servo2*2 );//ch2= 3B t3=get_time(); I2C_IO_WriteReg16( i2cDev, ch3, servo3*2 );//ch3= 3A t4=get_time(); I2C_IO_WriteReg16( i2cDev, ch5, servo5*2 );//ch5= 1B t5=get_time(); printf("(Servo1) T1-T2:%f,(Servo2) T2-T3:%f,(Servo3) T3-T4:%f, (Servo4) T4-T5:%f\n", (t2-t1)*1000,(t3-t2)*1000,(t4-t3)*1000,(t5-t4)*1000); END CODE SEGMENT OUTPUT (Last 9 Runs): (Servo1) T1-T2:0.926000,(Servo2) T2-T3:18.559000,(Servo3) T3-T4:0.909000, (Servo4) T4-T5:19.080000 (Servo1) T1-T2:0.932000,(Servo2) T2-T3:18.468000,(Servo3) T3-T4:19.995000, (Servo4) T4-T5:20.000000 (Servo1) T1-T2:0.935000,(Servo2) T2-T3:18.521000,(Servo3) T3-T4:19.994000, (Servo4) T4-T5:20.000000 (Servo1) T1-T2:0.931000,(Servo2) T2-T3:18.523000,(Servo3) T3-T4:19.995000, (Servo4) T4-T5:20.010000 (Servo1) T1-T2:0.951000,(Servo2) T2-T3:18.474000,(Servo3) T3-T4:19.997000, (Servo4) T4-T5:19.999000 (Servo1) T1-T2:0.928000,(Servo2) T2-T3:18.490000,(Servo3) T3-T4:19.995000, (Servo4) T4-T5:20.000000 (Servo1) T1-T2:0.935000,(Servo2) T2-T3:18.513000,(Servo3) T3-T4:19.996000, (Servo4) T4-T5:20.000000 (Servo1) T1-T2:0.928000,(Servo2) T2-T3:18.899000,(Servo3) T3-T4:1.013000, (Servo4) T4-T5:18.617000 (Servo1) T1-T2:0.926000,(Servo2) T2-T3:18.409000,(Servo3) T3-T4:19.995000, (Servo4) T4-T5:20.000000 What I Meant was that consistently the consecutive second (ch2,servo2), third(ch3,servo3) and fourth(ch4,servo4) WriteReg16 commands are running at different speeds. There is no other code in between except the timer function. Is there something I should be doing in between WriteReg16 calls? How can it take one consistent time to write to 1 register and a significantly larger time to write to a different one. Note how sometimes in the writereg call for servo 3 it only takes about 1 ms. Once again thanks for your quick responses, -Shawn |
From: Shawn C. <scy...@gm...> - 2008-03-24 05:52:11
|
Hi Dave, The current buildroot revision on my gumstix is 1585. Heres a list of all other running processes: START PROCESS LIST-------------------------------------------------------------- PID Uid VmSize Stat Command 1 root 380 S init 2 root SWN [ksoftirqd/0] 3 root SW [watchdog/0] 4 root SW< [events/0] 5 root SW< [khelper] 6 root SW< [kthread] 26 root SW< [kblockd/0] 38 root SW [pdflush] 39 root SW [pdflush] 40 root SW< [kswapd0] 41 root SW< [aio/0] 120 root SW [mtdblockd] 139 root SWN [jffs2_gcd_mtd1] 162 root 308 S < /sbin/udevd --daemon 174 root SW< [kmmcd] 218 root SW< [pccardd] 226 root SW< [ksuspend_usbd] 231 root SW< [khubd] 297 dbus 800 S dbus-daemon --config-file=/etc/dbus-1/system.conf 346 root 112 S /usr/sbin/hciattach -s 57600 ttyS1 gumstix 921600 flo 353 root 940 S /usr/sbin/hcid -s -f /etc/bluetooth/hcid.conf 367 root 268 S rfcomm -r watch 0 1 /sbin/getty -w -L rfcomm0 115200 371 root SW< [krfcommd] 414 root 416 S /usr/sbin/mDNSResponder -f /etc/bonjour.conf -b 429 root 372 S /usr/sbin/dropbear 435 www-data 276 S /usr/sbin/boa 439 root 476 S -sh 440 root 392 S /sbin/getty -L tty0 115200 linux 443 root 364 S /sbin/syslogd -n -m 0 444 root 352 S /sbin/klogd -n 482 root 364 R ps END PROCESS LIST---------------------------------------------------------------------------- Here is the get_time function: double get_time(void) { struct timeval stime; gettimeofday (&stime, (struct timezone*)0); return (stime.tv_sec+((double)stime.tv_usec)/1000000); } There is no other threads running I know of. This should be the only program using the i2c bus unless there's something I'm unaware of. I've restarted the gumstix multiple times, reran "modprobe i2c-dev; modprobe i2c-pxa" but I still get the same latency in my functionality. PLEASE HELP if you have any suggestions, this is driving me crazy. Your help is always much appreciated, once again thanks! -Shawn |
From: Shawn C. <scy...@gm...> - 2008-03-24 08:38:33
|
Sorry I feel like I'm spamming the mail list, but I needed to show this as I've officially entered the twilight zone. I've created test code which in main does the following: while(1) { switch(i) { case 0: t3=get_time(); t1=get_time(); I2C_IO_WriteReg16( i2cDev, ch1, servo1*2 );//ch1= 3C t2=get_time(); printf("(Servo1) T1-T2:%f\n", (t2-t1)*1000); i=1; break; case 1: t1=get_time(); I2C_IO_WriteReg16( i2cDev, ch2, servo2*2 );//ch2= 3B t2=get_time(); printf("(Servo2) T1-T2:%f\n", (t2-t1)*1000); i=2; break; case 2: t1=get_time(); I2C_IO_WriteReg16( i2cDev, ch3, servo3*2 );//ch3= 3A t2=get_time(); printf("(Servo3) T1-T2:%f\n", (t2-t1)*1000); i=3; break; case 3: t1=get_time(); I2C_IO_WriteReg16( i2cDev, ch5, servo5*2 );//ch5= 1B t2=get_time(); printf("(Servo4) T1-T2:%f\n", (t2-t1)*1000); i=4; t4=get_time(); printf("(Total Time):%f\n", (t4-t3)*1000); break; case 4: t1=get_time(); I2C_IO_WriteReg16( i2cDev, ch1, servo1*2 );//ch1= 3C I2C_IO_WriteReg16( i2cDev, ch2, servo2*2 );//ch2= 3B I2C_IO_WriteReg16( i2cDev, ch3, servo3*2 );//ch3= 3A I2C_IO_WriteReg16( i2cDev, ch5, servo5*2 );//ch5= 1B t2=get_time(); printf("(Total Time Consecutive Writes):%f\n\n", (t2-t1)*1000); i=0; break; } } What this does is each time the main loop runs it sets 1 16 bit register for the PWM. Then on the 4th run of the loop (i=4) it sets the last of the set of 4 PWMS. The time it takes to set each register is measured along with the total time it takes to write the 4 PWM registers (loop 4 times). In addition to this on every fourth loop (i=4) the program attempts to consecutively set all four registers one after another and times the total time to set these four PWM registers. Thia is the output for three runs: (Servo1) T1-T2:0.907000 (Servo2) T1-T2:0.899000 (Servo3) T1-T2:0.916000 (Servo4) T1-T2:0.897000 (Total Time):4.127000 (Total Time Consecutive Writes):55.605000 (Servo1) T1-T2:0.908000 (Servo2) T1-T2:0.899000 (Servo3) T1-T2:0.920000 (Servo4) T1-T2:0.897000 (Total Time):4.135000 (Total Time Consecutive Writes):36.839000 (Servo1) T1-T2:0.885000 (Servo2) T1-T2:0.896000 (Servo3) T1-T2:0.884000 (Servo4) T1-T2:0.890000 (Total Time):4.029000 (Total Time Consecutive Writes):54.340000 How is this possible. It is literally faster to in a loop to set four registers one register at a time then to consecutively set the four registers in code over the i2c bus. Could this be some time of strange timing issue that I am not seeing. Lol if I have a control loop and set only 1 PWM at a time, four iterations of the controller is almost ten times faster then if I try setting all 4 PWM registers every loop. Once again thanks for any responses, -Shawn |
From: Dave H. <dhy...@gm...> - 2008-03-24 14:46:49
|
Hi Shawn, > What this does is each time the main loop runs it sets 1 16 bit register for > the PWM. Then on the 4th run of the loop (i=4) it sets the last of the set > of 4 PWMS. The time it takes to set each register is measured along with the > total time it takes to write the 4 PWM registers (loop 4 times). In addition > to this on every fourth loop (i=4) the program attempts to consecutively set > all four registers one after another and times the total time to set these > four PWM registers. Thia is the output for three runs: > (Servo1) T1-T2:0.907000 > (Servo2) T1-T2:0.899000 > (Servo3) T1-T2:0.916000 > (Servo4) T1-T2:0.897000 > (Total Time):4.127000 > (Total Time Consecutive Writes):55.605000 ...snip... > How is this possible. It is literally faster to in a loop to set four > registers one register at a time then to consecutively set the four > registers in code over the i2c bus. Could this be some time of strange > timing issue that I am not seeing. Lol if I have a control loop and set only > 1 PWM at a time, four iterations of the controller is almost ten times > faster then if I try setting all 4 PWM registers every loop. I took a look at the i2c driver, and if the bus is deemed to be busy, then it does an msleep( 2 ). Since it's sleeping, this means that it will actually sleep in units of jiffies, and since it doesn't know where it is in the current jiffy, it will sleep for a minimum of 2 jiffies. So I suspect it's a timing thing, and something is happening at the end of the previous write in that the bus isn't quite free at the tail end of previous request, and if the next request happens just a tad too quickly then it winds up doing the msleep. That's all conjecture on my part, but it seems like it might be plausible. -- Dave Hylands Vancouver, BC, Canada http://www.DaveHylands.com/ |
From: Dave H. <dhy...@gm...> - 2008-03-24 04:49:20
|
Hi Shawn, > What I Meant was that consistently the consecutive second (ch2,servo2), > third(ch3,servo3) and fourth(ch4,servo4) WriteReg16 commands are running at > different speeds. There is no other code in between except the timer > function. Is there something I should be doing in between WriteReg16 calls? > How can it take one consistent time to write to 1 register and a > significantly larger time to write to a different one. Note how sometimes in > the writereg call for servo 3 it only takes about 1 ms. Not sure why they would take any differing amounts of time unless somebody else was using the i2c bus. What version of buildroot/OE are you using? What does your get_time function look like? Do you have any other threads running? -- Dave Hylands Vancouver, BC, Canada http://www.DaveHylands.com/ |