I2C send and receive in mainline while also running code in ISR
![Zoot](https://forums.parallax.com/uploads/userpics/559/nW4UO23UEIWZ4.png)
I'm reworking my SX servo controller (http://forums.parallax.com/showthread.php?p=703230) to handle my new motor encoders, wheel odometry and PID velocity. This is in addition to existing servo control. I'm pretty much rewriting the whole thing (extending avail. pulsewidths, going to 4us resolution, freeing up space for encoder, PID, odometry code and var space).
My main motor driver (an MD22) is I2C based, and while I can configure it to accept servo pulses, I would rather use it as I2C. So..... am I correct in presuming that I can do my I2C sends to the driver in my mainline program and not worry about about my ISR? Since I2C is clocked, and I only need to send 3 bytes to the driver, and since I've shortened my ISR *radically*, this will technically work, right? Worst case might be that the I2C clock could get slooowish if the ISR is bogging things down?
I'm doing a quasi-multi-thread setup ala pjv -- with the exception of servo pulses, tx/rx and encoder ticks, the ISR only sets flags and timers for various "task-like" chores in the mainline program (i.e. servo timers are reset every 20ms by the mainline, PID updated every 50ms by the mainline, I2C sent to motor driver every 50ms in the mainline, odometry chores are done every 100ms or when the tick count is high enough to warrant it, etc.
Pseudo code:
Naturally I'm leaving out lots here (like the PID includes two timers -- one for the frame, one to measure actual time since last sampling, so that if the mainline "misses" a frame at the price 100ms timeout, it will still be able to decent calculations, or that I'll be staggering the initial values for the frame timers so that, most of the time, the "frames" will never all run at once).
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
When the going gets weird, the weird turn pro. -- HST
1uffakind.com/robots/povBitMapBuilder.php
1uffakind.com/robots/resistorLadder.php
My main motor driver (an MD22) is I2C based, and while I can configure it to accept servo pulses, I would rather use it as I2C. So..... am I correct in presuming that I can do my I2C sends to the driver in my mainline program and not worry about about my ISR? Since I2C is clocked, and I only need to send 3 bytes to the driver, and since I've shortened my ISR *radically*, this will technically work, right? Worst case might be that the I2C clock could get slooowish if the ISR is bogging things down?
I'm doing a quasi-multi-thread setup ala pjv -- with the exception of servo pulses, tx/rx and encoder ticks, the ISR only sets flags and timers for various "task-like" chores in the mainline program (i.e. servo timers are reset every 20ms by the mainline, PID updated every 50ms by the mainline, I2C sent to motor driver every 50ms in the mainline, odometry chores are done every 100ms or when the tick count is high enough to warrant it, etc.
Pseudo code:
ISR: update encoder ticks update tx/rx (4 byte buffer to/from serial port) update servo pulses dec rampFrame dec PIDframe dec ODframe DONE Main: IF rampFrame = 0 THEN rampFrame = some constant update all servo target pulses with new ramped values ENDIF IF PIDframe = 0 THEN PIDframe = some constant update PID velocity I2CSEND to motor driver ENDIF IF ODframe = 0 THEN ODframe = some constant update odometry ENDIF IF serialBuffCnt > 0 THEN parse and distribute incoming serial commands setup tx buff if response is required ENDIF GOTO Main
Naturally I'm leaving out lots here (like the PID includes two timers -- one for the frame, one to measure actual time since last sampling, so that if the mainline "misses" a frame at the price 100ms timeout, it will still be able to decent calculations, or that I'll be staggering the initial values for the frame timers so that, most of the time, the "frames" will never all run at once).
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
When the going gets weird, the weird turn pro. -- HST
1uffakind.com/robots/povBitMapBuilder.php
1uffakind.com/robots/resistorLadder.php
Comments
so far, i did many SX applications with an I2C master interface, and I never made the I2C code part of the ISR. The nice fact is that the master generates the SCL clock signal, and the slaves on the bus nicely sync to that clock, no matter if it is yittery or not. IOW: It absolutely does not matter if some time-critical ISR code messes up the mainline's I2C timing. So I can only confirm that you may do your I2C sends in your mainline program w/o worrying about the resulting timing errors.
BTW: I noticed that you let the ISR update servo pulses and encoder ticks. In similar applications, I use the port B edge-detection feature, and check for port B transitions in the mainline program loop as this is usually executed at a higher repeat rate than the ISR code.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Greetings from Germany,
G
I thought about this, but in this particular application I'm getting, for discussion's sake, 2-40 encoder ticks every50 ms -- pretty slow. Average speed is around 12 ticks per 50ms. The ISR will be running every 4 us.
My rough estimate is that the mainline I2CSEND (as a master) could take from 1 - 2 ms (depending on how many bytes I choose to send and/or receive, and NOT including add'l overhead of ISRs that will surely be callled between instructions during mainline I2C transactions) so it would seem that my ISR will run much more often (more accurately, during mainline frames when I2C transactions and frame calculations are taking place).
Additionally, my estimate is that some of the long division for my PID and odometry *could* take some hundreds of instruction cycles for each calculation -- and depending on what odometry and PID is really being calculated (if no distance has been traveled or velocity read is the same, obviously, PID and odometry do not need to be recalculated, saving some 1000s of looped instructions for divides, multiplies, etc). Add to that IREADS for sin/cosine lookups, setting up the TX buffer to respond to queries from the host, etc. and things add up a bit for the mainline.
In short, I've been budgeting a 1ms-4ms time in the mainloop during frames execution (servos, PID, odometry) at 50mhz and upon updates from the host via serial RX...
And that's before I possibly add in some of the 32bit math routines I've been checking out from Scenix/SXlist
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
When the going gets weird, the weird turn pro. -- HST
1uffakind.com/robots/povBitMapBuilder.php
1uffakind.com/robots/resistorLadder.php