|
View:
New views
5 Messages
—
Rating Filter:
Alert me
|
|
|
Verdex + Robostix - Combining I2C with a Controller?Hi, List,
Using a Verdex XM4BT and a Robostix, I have long had the i2c-io code (by Dave Hylands) working, with some modifications for time-regular data logging to the gumstix (~100 hz). A separate project uses the Robostix as a servo controller, operating based on some analog sensors. The code is extremely simple, just a couple dozen lines. I am now trying to combine these two functions, so I can use i2c-io and my data logging modifications while the controller is running. However, when I combine the controller code (based on the Simple-Servo example) with the i2c-io code, I get i2c failures - specifically, the robostix no longer passes the correct i2c commands to the i2c-io "ProcessCommand" function. I know this because when my gumstix code sends command 11 (0x0b, case "I2C-IO-Get-ADCs"), the i2c-io function "ProcessCommand" receives command 3 (0x03, which is case "I2C-IO-SET-GPIO") [tested by turning LEDs uniquely within various commands until I found the one that was receiving it]. Then I assume there is an error, and what gets returned must be junk of some kind to cause these error messages: I get errors back such as: 1) [for a call for a single ADC channel] root@gumstix-custom-verdex:~$ i2c-io 0x0b get ADC.0 ERROR: I2cTransfer: length is too big: 3 max: 2 ERROR: I2cTransfer: CRC failed: Rcvd: 0xff, expecting: 0x24 ERROR: I2C_IO_GetADC: I2cProcessBlock failed: Success (0) ERROR: Failed to retrieve value for ADC.0 2) [for a call to get multiple ADC channels per my special i2c command "I2C_IO_GET_ADCs", asking for 5 channels (10 bytes)] ERROR: I2cTransfer: length is too big: 188 max: 10 ERROR: I2cTransfer: CRC failed: Rcvd: 0xff, expecting: 0xf5 ERROR: I2C_IO_GetADCs: I2cProcessBlock failed: Inappropriate ioctl for device (25) The Question is: Is there any known reason that the PWM outputs, Timers, Analog inputs, or any other normal controller code would interfere with i2c communications? My code below, based on i2c-io and Simple-Servo. This code interfaces to other standard functions in the Robostix sample libraries. Thanks for any help anyone can offer, Peter Code: /** * * @file RNL_Controller * * @brief This file implements (1) a Controller for the RNL, and (2) a set of I2C commands which allows the * robostix I/O to be controlled by the gumstix. * * Modified from i2c-io, by Dave Hylands * *****************************************************************************/ /* ---- Include Files ----------------------------------------------------- */ #include <avr/io.h> #if defined( __AVR_LIBC_VERSION__ ) # include <avr/interrupt.h> #else # include <avr/signal.h> #endif #include <compat/twi.h> #include <stdio.h> #include <inttypes.h> #include "i2c-io.h" #include "Hardware.h" #include "i2c-slave-boot.h" #include "Log.h" #include "Delay.h" #include "Timer.h" #include "UART.h" //#include "Config.h" //#include "Config-LED.h" //#include "Robostix.h" #include "svn-version.h" //Peter's #include "a2d.h" //#include "Config.h" #include "PinPulse.h" // //Peter's /* ---- Public Variables -------------------------------------------------- */ /* ---- Private Constants and Types --------------------------------------- */ /* ---- Private Variables ------------------------------------------------- */ //-------------------------------------------------------------------------- // // Servo pins (relies on definitions from Timer.h) // #define SERVO_1 3A #define SERVO__( ocr, reg ) TIMER_ ## ocr ## _ ## reg #define SERVO_( ocr, reg ) SERVO__( ocr, reg ) #define SERVO( num, reg ) SERVO_( SERVO_ ## num, reg ) //-------------------------------------------------------------------------- // Program Constants // #define numpts 15u // Points to average in the moving average #define walkingmovavgthresh 14u // Number of bits away from the 2.5V Nominal Output that the "numpts" -point moving average should be to indicate Walking mode. #define walkmode_usec 900u // Microseconds for the Servo Pulse that commands Walking mode #define standmode_usec 2100u // Microseconds for the Servo Pulse that commands Standing mode #define decisiondelay 100 // Number of Cycles (at 100Hz) to wait after changing the state before it can change again. // //Peter's #define TCNT2DIVISOR TIMER2_CLOCK_SEL_DIV_1024 // Set the Timer2 Clock Divisor (divisor for 16 MHz clock) #define TCNT2RESETVALUE 99 // With 1024 Divisor, setting the Reset value to be 99 yields 100 Hz interrupts on Timer2: 16e6/1024/(255-99) = 100.1603 //Peter's // Output (Interrupt Pulse on PORTE.2) // Make pin 2 on Port E an output, ready to Interrupt the Gumstix #define GumInt_DDR DDRE #define GumInt_PORT PORTE #define GumInt_PIN PINE #define GumInt_PIN_MASK ( 1 << DDE2 ) // Pin 0: 1 is a bit that selects a channel. DDE2 shifts it left (<<) DDE2 positions. // //Peter's #define TCNT2RESET 99 // Fake out ports that don't exist #define NUM_PORTS 7 #if !defined( PORTA ) #define PORTA PORTB #define DDRA DDRB #define PINA PINB #endif #if !defined( PORTE ) #define PORTE PORTB #define DDRE DDRB #define PINE PINB #endif #if !defined( PORTF ) #define PORTF PORTB #define DDRF DDRB #define PINF PINB #endif #if !defined( PORTG ) #define PORTG PORTB #define DDRG DDRB #define PING PINB #endif volatile uint8_t *gPORT[ NUM_PORTS ] = { &PORTA, &PORTB, &PORTC, &PORTD, &PORTE, &PORTF, &PORTG }; volatile uint8_t *gDDR[ NUM_PORTS ] = { &DDRA, &DDRB, &DDRC, &DDRD, &DDRE, &DDRF, &DDRG }; volatile uint8_t *gPIN[ NUM_PORTS ] = { &PINA, &PINB, &PINC, &PIND, &PINE, &PINF, &PING }; /* ---- Private Function Prototypes --------------------------------------- */ #undef LED_ON #undef LED_OFF #define LED_OFF() do { CFG_BOOTLOADER_BEAT_PORT &= ~CFG_BOOTLOADER_BEAT_MASK; } while (0) #define LED_ON() do { CFG_BOOTLOADER_BEAT_PORT |= CFG_BOOTLOADER_BEAT_MASK; } while (0) #define IO_LOG_ENABLED 0 #if IO_LOG_ENABLED # define IO_LOG0( fmt ) LogBuf0( "IO: " fmt ) # define IO_LOG1( fmt, arg1 ) LogBuf1( "IO: " fmt, arg1 ) # define IO_LOG2( fmt, arg1, arg2 ) LogBuf2( "IO: " fmt, arg1, arg2 ) # define IO_LOG3( fmt, arg1, arg2, arg3 ) LogBuf3( "IO: " fmt, arg1, arg2, arg3 ) #else # define IO_LOG0( fmt ) # define IO_LOG1( fmt, arg1 ) # define IO_LOG2( fmt, arg1, arg2 ) # define IO_LOG3( fmt, arg1, arg2, arg3 ) #endif int ProcessCommand( I2C_Data_t *packet ); /* ---- Functions --------------------------------------------------------- */ //*************************************************************************** /** * Main loop for the I2C I/O program. */ int main(void) { uint8_t i = 0; uint8_t j = 0; uint8_t k = 0; uint16_t AnalogBuffer[ numpts ]; for (i=0; i<numpts; i++) { AnalogBuffer[i]=0; } InitHardware(); // CFG_BOOTLOADER_BEAT_DDR |= CFG_BOOTLOADER_BEAT_MASK; // The first handle opened for read goes to stdin, and the first handle // opened for write goes to stdout. So u0 is stdin, stdout, and stderr #if IO_LOG_ENABLED #if defined( __AVR_LIBC_VERSION__ ) fdevopen( UART0_PutCharStdio, UART0_GetCharStdio ); #else fdevopen( UART0_PutCharStdio, UART0_GetCharStdio, 0 ); #endif LogInit( stdout ); Log( "*****\n" ); Log( "***** I2C I/O program (I2C addr: 0x%02x\n", TWAR >> 1 ); Log( "*****\n" ); #endif // IO_LOG_ENABLED if ( !I2C_SlaveBootInit( ProcessCommand )) { LogError( "I2C_SlaveBootInit failed\n" ); while ( 1 ) { ; } } //Peter's // GumInt Pin Initialization GumInt_DDR |= GumInt_PIN_MASK; // Configure as an output by setting the relevant pin's direction (DDR) high GumInt_PORT &= ~GumInt_PIN_MASK; // Set the pin state Low to begin // Clock for Encoder Interrupts // Setup Timer2 to overflow about 61 times per second (8 bit = 256 counts, at [16MHz]/[1024 prescaler]). TCCR2 = TIMER2_CLOCK_SEL_DIV_1024; //This line sets the clock speed for the Timer2 (= 16000000 / 1024) //TCCR2 = TIMER2_CLOCK_SEL_DIV_256; // Wisit's, test for 61*4 = ~ 244 Hz. (in reality, results in ~106 Hz.) //TCCR2 = TIMER2_CLOCK_SEL_DIV_64; TIMSK |= ( 1 << TOIE2 ); //Set Timer Interrupt MaSK (one byte, all zeros initially) to have a 1 in spot TOIE2 (Timer Overflow Interrupt Enable 2), which is Bit 6 of TIMSK. // toe_pot_neutral = toe_pot_neutral + (uint16_t)gADC[ 0 ]; // Not sure what the (uint16_t) part does...maybe a type conversion? // Initialize LEDs // LED_ON( ); // //Peter's sei(); // If we run Timer 3 (a 16 bit timer) at 2 MHz (divide by 8 prescalar) // then it will overflow every 32.7 msec which is suitable for driving // R/C servos. // // However, we can do better. If we set TOP to 40,000, we get // 40,000 1/2 usec (i.e. 2 MHz) counts or about 20 msec between pulses // (50 Hz) which is an even better pulse rate for R/C servos. // // We use WGM mode 14, Fast PWM with the TOP value supplied by ICR3. // We use COM mode 2, which causes the OC3x pin to be cleared (0) on a match // with OCR3x and set (1) when the timer reaches TOP. ICR3 = 40000u; SERVO( 1, OCR ) = 1500u * 2; // 1500 usec is servo mid point; //This statement goes through Macros above to become "TIMER_3A_OCR = 1500u*2". After Timer.h, it is "OCR3A = 1500u*2" TCNT3 = 0; // Set the WGM mode & prescalar (Waveform Generation Mode): WGM = 0b1110 = 14 in decimal: Fast PWM using ICR3 (Input Compare Register value) as TOP TCCR3A = ( 1 << WGM31 ) | ( 0 << WGM30 ); // WGM31 and WGM30 are the rightmost bits of TCCR3A (p133 of ATMega 128 manual) TCCR3B = ( 1 << WGM33 ) | ( 1 << WGM32 ) | TIMER3_CLOCK_SEL_DIV_8; // WGM33 and WGM32 are in the middle of TCCR3B // TIMER3_CLOCK_SEL_DIV_8 sets the Right 3 bits. These three bits control the Prescaler. // The Left two bits are for Input Capture options. Bit 6 is unused. // Set the servo pins to COM (Compare Output Mode) mode 2 (COM_1 = 1, COM_0 = 0): ATMega 128 manual p134 // This causes the OCR pin to fall when the counter reaches the value // stored in the OCR register and causes the OCR pin to rise when the // counter reaches TOP (gets reset to zero). SERVO( 1, TCCRA ) |= ( 1 << SERVO( 1, COM_1 )); // Calls the Macros defined above to become: "TIMER_3A_TCCRA |= TIMER_3A_COM_1;". Further definitions of these variables are in Timer.h. End result is: "TCCR3A |= // Set the servo pins to be outputs SERVO( 1, DDR ) |= SERVO( 1, MASK ); // Calls the Macros defined above to become: "TIMER_3A_DDR |= TIMER_3A_MASK". Further definitions in Timer.h give "DDRE |= 0b00001000": that is, set Pin 3 of Port E to be an Output. uint16_t sample = 0; uint16_t movingsum = 0; uint16_t walkingmovsumthresh = numpts*walkingmovavgthresh ; uint16_t pulse1_usec; while( 1 ) { ; for (j=0; j<numpts; j++) // Adamczyk's loop for getting an Analog sample to fill a buffer, and update a moving average { // Read the ADC's sample = a2d_10( 0 ) ; // read Channel 0 through functions in a2d_10.c, as included by a2d.h movingsum -= AnalogBuffer[ j ] ; // Remove the obsolete sample from the Moving Sum AnalogBuffer[ j ] = abs( sample - 511u) ; // Store in the Buffer the absolute value of the difference between the Sample and 511 (where 511 bits == 2.5V) movingsum += AnalogBuffer[ j ] ; // Add the new Sample to the Moving Sum if ( k >= decisiondelay) // Only allow a state switch if the decision delay counter "k" has exceeded the specified delay. { if (movingsum > walkingmovsumthresh) // IF the moving sum of absolute deviations from 0 angular velocity (in bits) is greater than the threshold value... THEN we are in Walking. { if (pulse1_usec == standmode_usec) // detect if current mode setting is Stand { k = 0; } // If so, then the present setting to WALK is a Switch; reset the delay counter. pulse1_usec = walkmode_usec; // Set the control to Walking mode. // LED_ON(YELLOW); // LED_OFF(BLUE); } else // ELSE we are in Standing. { if (pulse1_usec == walkmode_usec) // detect if current mode setting is Walk { k = 0; } // If so, then the present setting to STAND is a Switch; reset the delay counter. pulse1_usec = standmode_usec; // Set the control to Standing mode. // LED_OFF(YELLOW); // LED_ON(BLUE); k = 0; } //end of "if-else" } //end of "if k >= decisiondelay" else // else k < decisiondelay { k++; } // increment k only if it is not over the "decisiondelay" threshold // We then need to multiply the pulse in usec by 2, since our timer // runs with 1/2 usec ticks. // Note that The OCR3x registers are double buffered so we can set them at any // time. SERVO( 1, OCR ) = pulse1_usec * 2; // * 2 is because timer ticks every 1/2 usec. // Command translates to "OCR3A = pulse1_usec *2" // We put a delay in here so we aren't trying to update the OCR // registers too frequently. WaitForTimer0Rollover(); // This Rollover occurs every 10 msec (100 Hz), so we are stuck with that sample rate if we use this function for the delay. if (j==-10) { LED_TOGGLE( RED ); } //Just for fun, toggle Red LED at each recycle of the buffer. } // end of "for j<numpts" } // end "while (1)" loop return 0; } // main //*************************************************************************** /** * I2C Interrupt service routine */ SIGNAL(SIG_2WIRE_SERIAL) { if ( !I2C_SlaveBootHandler() ) { LogError( "Unrecognized status: 0x%x\n", TW_STATUS ); } // Now that we've finished dealing with the interrupt, set the TWINT flag // which will stop the clock stretching and clear the interrupt source TWCR |= ( 1 << TWINT ); } // SIG_2WIRE_SERIAL // Peter's code to signal Port.E2 //Tell the board to produce a pulse when Timer 2 overflows ISR( TIMER2_OVF_vect ) //This sets the "Interrupt Service Routine" that happens when Timer2 Overflows { PinPulse_Issue( GumInt ); //The routine is "PinPulse," which rapidly puts the pin high and then low. TCNT2 = TCNT2RESET; // Reset the TCNT2 Register to a non-zero value to fine-tune the frequency. This value can be between 0 and 255. The Frequency achieved will depend on the Prescaler as well. For prescaler = 256 and TCNT2 reset value = 130, we should interrupt at exactly 500 Hz. It works pretty well, though 500hz appears to be too fast for 8 channels even in fast mode of i2c. //GumInt is a string that will be prepended to a bunch of variable names to make the functions happen } // //Peter's //*************************************************************************** /** * Callback called to process incoming i2c commands. */ int ProcessCommand( I2C_Data_t *packet ) { int rc; uint8_t cmd = packet->m_data[ 0 ]; switch ( cmd ) { case I2C_IO_GET_INFO: { I2C_IO_Info_t *info = (I2C_IO_Info_t *)&packet->m_data[ 1 ]; IO_LOG0( "GetInfo\n" ); info->version = I2C_IO_API_VERSION; info->minVersion = I2C_IO_API_MIN_VERSION; info->svnRevision = SVN_REVISION; packet->m_data[ 0 ] = sizeof( *info ); return sizeof( *info ) + 1; // + 1 for len } case I2C_IO_GET_GPIO: { I2C_IO_Get_GPIO_t *req = (I2C_IO_Get_GPIO_t *)&packet->m_data[ 2 ]; // +1 for cmd, +1 for len uint8_t portNum = req->portNum; if ( portNum > NUM_PORTS ) { portNum = 0; } packet->m_data[ 0 ] = 1; packet->m_data[ 1 ] = *(gPIN[ portNum ]); IO_LOG2( "GetGPIO Port %c: 0x%02x\n", portNum + 'A', packet->m_data[ 1 ]); return 2; } case I2C_IO_SET_GPIO: { I2C_IO_Set_GPIO_t *req = (I2C_IO_Set_GPIO_t *)&packet->m_data[ 2 ]; // +1 for cmd, +1 for len uint8_t portNum = req->portNum; uint8_t pinMask = req->pinMask; uint8_t pinVal = req->pinVal; if ( portNum > NUM_PORTS ) { portNum = 0; } IO_LOG3( "SetGPIO Port %c: Mask:0x%02x Val:0x%02x\n", portNum + 'A', pinMask, pinVal ); *(gPORT[ portNum ]) &= ~pinMask; *(gPORT[ portNum ]) |= ( pinVal & pinMask ); return 0; } case I2C_IO_GET_GPIO_DIR: { I2C_IO_Get_GPIO_t *req = (I2C_IO_Get_GPIO_t *)&packet->m_data[ 2 ]; // +1 for cmd, +1 for len uint8_t portNum = req->portNum; if ( portNum > NUM_PORTS ) { portNum = 0; } packet->m_data[ 0 ] = 1; packet->m_data[ 1 ] = *(gDDR[ portNum ]); IO_LOG2( "GetGPIODir Port %c: 0x%02x\n", portNum + 'A', packet->m_data[ 1 ]); return 2; } case I2C_IO_SET_GPIO_DIR: { I2C_IO_Set_GPIO_t *req = (I2C_IO_Set_GPIO_t *)&packet->m_data[ 2 ]; // +1 for cmd, +1 for len uint8_t portNum = req->portNum; uint8_t pinMask = req->pinMask; uint8_t pinVal = req->pinVal; if ( portNum > NUM_PORTS ) { portNum = 0; } IO_LOG3( "SetGPIODir Port %c: Mask:0x%02x Val:0x%02x\n", portNum + 'A', pinMask, pinVal ); *(gDDR[ portNum ]) &= ~pinMask; *(gDDR[ portNum ]) |= ( pinVal & pinMask ); return 0; } case I2C_IO_GET_ADC: { I2C_IO_Get_ADC_t *req = (I2C_IO_Get_ADC_t *)&packet->m_data[ 2 ]; // +1 for cmd, +1 for len uint8_t mux = req->mux; // Set ADMUX but don't mess with REFS0 & REFS1 ADMUX = ( ADMUX & (( 1 << REFS1 ) | ( 1 << REFS0 ))) | mux; // Start the conversion ADCSR = ADCSR | ( 1 << ADSC ); // Wait for it to complete while ( ADCSR & ( 1 << ADSC )); packet->m_data[ 0 ] = 2; packet->m_data[ 1 ] = ADCL; packet->m_data[ 2 ] = ADCH; IO_LOG3( "GetADC mux:%d read 0x%02x%02x\n", mux, packet->m_data[ 2 ], packet->m_data[ 1 ]); return 3; } case I2C_IO_READ_REG_8: { I2C_IO_ReadReg8_t *req = (I2C_IO_ReadReg8_t *)&packet->m_data[ 2 ]; // +1 for cmd, +1 for len volatile uint8_t *regPtr = (volatile uint8_t *)(int)(req->reg); packet->m_data[ 0 ] = 1; packet->m_data[ 1 ] = *regPtr; IO_LOG2( "ReadReg8 reg:0x%02x read 0x%02x\n", (uint8_t)(int)regPtr, packet->m_data[ 1 ]); return 2; } case I2C_IO_READ_REG_16: { I2C_IO_ReadReg16_t *req = (I2C_IO_ReadReg16_t *)&packet->m_data[ 2 ]; // +1 for cmd, +1 for len volatile uint16_t *regPtr = (volatile uint16_t *)(int)(req->reg); uint16_t regVal = *regPtr; packet->m_data[ 0 ] = 2; packet->m_data[ 1 ] = (uint8_t)( regVal & 0xFF ); packet->m_data[ 2 ] = (uint8_t)(( regVal >> 8 ) & 0xFF ); IO_LOG3( "ReadReg16 reg:0x%02x read 0x%02x%02x\n", (uint8_t)(int)regPtr, packet->m_data[ 2 ], packet->m_data[ 1 ]); return 3; } case I2C_IO_WRITE_REG_8: { I2C_IO_WriteReg8_t *req = (I2C_IO_WriteReg8_t *)&packet->m_data[ 2 ]; // +1 for cmd, +1 for len volatile uint8_t *regPtr = (volatile uint8_t *)(int)(req->reg); *regPtr = req->val; IO_LOG2( "WriteReg8 reg:0x%02x wrote 0x%02x\n", (uint8_t)(int)regPtr, req->val); return 0; } case I2C_IO_WRITE_REG_16: { I2C_IO_WriteReg16_t *req = (I2C_IO_WriteReg16_t *)&packet->m_data[ 2 ]; // +1 for cmd, +1 for len volatile uint8_t *regPtr = (volatile uint8_t *)(int)(req->reg); uint8_t valH = (( req->val >> 8 ) & 0xFF ); uint8_t valL = ( req->val & 0xFF ); // For writing 16 bit registers, we need to write the high byte first regPtr[ 1 ] = valH; regPtr[ 0 ] = valL; IO_LOG3( "WriteReg16 reg:0x%02x wrote 0x%02x%02x\n", (uint8_t)(int)regPtr, valH, valL ); return 0; } // Wisit's, multiple channels ADC data retrieving case I2C_IO_GET_ADCs: { I2C_IO_Get_ADC_t *req = (I2C_IO_Get_ADC_t *)&packet->m_data[ 2 ]; // +1 for cmd, +1 for len uint8_t mux = req->mux; // Set ADMUX but don't mess with REFS0 & REFS1 uint8_t iMux; packet->m_data[ 0 ] = 2*mux; for (iMux = 0; iMux < mux; iMux++) { ADMUX = ( ADMUX & (( 1 << REFS1 ) | ( 1 << REFS0 ))) | iMux; // Start the conversion ADCSR = ADCSR | ( 1 << ADSC ); // Wait for it to complete while ( ADCSR & ( 1 << ADSC )); //packet->m_data[ 0 ] = 2; packet->m_data[ 2*iMux+1 ] = ADCL; packet->m_data[ 2*iMux+2 ] = ADCH; } //IO_LOG3( "GetADC mux:%d read 0x%02x%02x\n", mux, packet->m_data[ 2 ], packet->m_data[ 1 ]); //return 3; return 2*mux+1; } } // It wasn't one of our commands, see if it's a bootloader command. if (( rc = I2C_SlaveBootProcessCommand( packet )) < 0 ) { LogError( "Unrecognized command: 0x%02x\n", cmd ); } return rc; } // ProcessCommand |
|
|
Re: Verdex + Robostix - Combining I2C with a Controller?Hi Peter,
On Wed, Oct 28, 2009 at 9:09 AM, p.g.adamczyk <p.g.adamczyk@...> wrote: > > Hi, List, > > Using a Verdex XM4BT and a Robostix, I have long had the i2c-io code (by > Dave Hylands) working, with some modifications for time-regular data logging > to the gumstix (~100 hz). ...snip... > // Peter's code to signal Port.E2 > > //Tell the board to produce a pulse when Timer 2 overflows > > ISR( TIMER2_OVF_vect ) //This sets the "Interrupt Service Routine" that > happens when Timer2 Overflows > > { > > PinPulse_Issue( GumInt ); //The routine is "PinPulse," which rapidly puts > the pin high and then low. > TCNT2 = TCNT2RESET; // Reset the TCNT2 Register to a non-zero value to > fine-tune the frequency. This value can be between 0 and 255. The Frequency > achieved will depend on the Prescaler as well. For prescaler = 256 and TCNT2 > reset value = 130, we should interrupt at exactly 500 Hz. It works pretty > well, though 500hz appears to be too fast for 8 channels even in fast mode > of i2c. > > //GumInt is a string that will be prepended to a bunch of variable names > to make the functions happen > > } So, I see that there is a call to PinPulse_Issue from inside an ISR handler. Note that interrupts are disabled while processing an interrupt handler, and as a general rule ISR handlers shouldn't contain any significant delays. If the code is just setting the pin high and then low with perhaps a few instructions between, then you should be fine. Otherwise, if the delay is significant (like anything over tens of microseconds), then this could be messing with the i2c interrupts. At 100 kHz, the i2c interrupts occur roughly once every 100 microseconds (during a transfer). Try disabling portions of your code to see if that makes the i2c stuff start working again. -- Dave Hylands Shuswap, BC, Canada http://www.DaveHylands.com/ ------------------------------------------------------------------------------ Come build with us! The BlackBerry(R) Developer Conference in SF, CA is the only developer event you need to attend this year. Jumpstart your developing skills, take BlackBerry mobile applications to market and stay ahead of the curve. Join us from November 9 - 12, 2009. Register now! http://p.sf.net/sfu/devconference _______________________________________________ gumstix-users mailing list gumstix-users@... https://lists.sourceforge.net/lists/listinfo/gumstix-users |
|
|
Re: Verdex + Robostix - Combining I2C with a Controller?Thanks, Dave, Alas, I have already disabled lots of stuff, and I have begun wondering whether it might be some sort of conflict in the definitions somewhere in the header files (?). The PinPulse ISR is as simple as you suggest, and should be no problem: pin_hi, nop, pin_low, return I know that does not cause problems on its own, because it works in my "enhanced" i2c-io program (with multiple ADCs in one return). I have disabled many sets of things. Here are the symptoms: Disable Timer2 (and thus prevent any PinPulse interrupt): manual i2c-io calls return the same errors Disable PWM outputs, and all the background definitions for them in the early part of the file: automatic (@100Hz) and manual calls to i2c-io functions all fail (same errors) Disable a2d_10 calls in the controller code: same errors *note that I have not commented out the header a2d.h - I will try this later Disable array storage and update in the controller code: same errors * Disable everything in my controller code, as well as the Timer2 interrupts and PWM outputs (Which should have returned the code to the same state as the original working "enhanced" i2c-io): same errors! Writing this, I feel like there may be an finger pointing at some conflict between the headers (??) needed/used for Simple-Servo and i2c-io. Perhaps the "a2d.h" file, which I realize I did not comment out during my tests. I will try commenting out the "a2d.h" header file and the analog sampling later, and see what happens. Are there any other definition conflicts or register conflicts you can think of between these two pieces of code? Thanks very much, -Peter
|
|
|
Re: Verdex + Robostix - Combining I2C with a Controller?Hi Peter,
> Writing this, I feel like there may be an finger pointing at some conflict > between the headers (??) needed/used for Simple-Servo and i2c-io. Perhaps > the "a2d.h" file, which I realize I did not comment out during my tests. I > will try commenting out the "a2d.h" header file and the analog sampling > later, and see what happens. There shouldn't be any conflicts. > Are there any other definition conflicts or register conflicts you can think > of between these two pieces of code? Perhaps you should try taking another approach. Start over with the original i2c-io.c and make sure that works. It's possible that it's a toolchain issue. Perhaps the i2c-Bootloader needs to be built using the same version of toolchain as i2c-io or something like that. Then incrementally add stuff to see when it breaks. -- Dave Hylands Shuswap, BC, Canada http://www.DaveHylands.com/ ------------------------------------------------------------------------------ Come build with us! The BlackBerry(R) Developer Conference in SF, CA is the only developer event you need to attend this year. Jumpstart your developing skills, take BlackBerry mobile applications to market and stay ahead of the curve. Join us from November 9 - 12, 2009. Register now! http://p.sf.net/sfu/devconference _______________________________________________ gumstix-users mailing list gumstix-users@... https://lists.sourceforge.net/lists/listinfo/gumstix-users |
|
|
Re: Verdex + Robostix - Combining I2C with a Controller?Thanks, Dave.
I went through another painstaking process of elimination as suggested, and ultimately the problem is fixed. Naturally it turned out to be something silly, not anything that should have required help. It turns out that I simply had the wrong versions of "Config.h" and "Hardware.h" in the project folder. This project needs the "i2c-io" versions, not the "Simple-Servo" versions. That's it :-\ Sorry for the help request, but thank you for giving your advice. -Peter
|
| Free embeddable forum powered by Nabble | Forum Help |