Odd behavior for sure. I need to do some more experiments. At very low speeds this should not be noise. I question if transitions out of the prop using outa[3..4] := %11 etc are valid methods for this type of quad output. I like the quadrature concept and it is faster to send quad than 4+ serial bytes. I tested today sending 4 bytes as position over 8” wires. 155k baud didn’t work. 80k works. But it is slower to create and read the packets in spin. I discovered that instead of the profile generator updating position at +1 per iteration I tried +2 per iteration on my test board sending the positions and that creates a faster motor speed without needing to run the data stream. The proof of concept is working out nicely to park 3 profile generators in one main board prop and stream positions to 3 sub boards running PID.
Serial.rx. ‘ wait for first byte
Serial.rxtime(10)
Serial.rxtime(10)
Serial.rxtime(10)
Outa[4]~ ‘tell sender to not send anymore
Position = Add 4 bytes together bit shifting each byte
Maybe there is a better way!
I’ll check the GND between both boards. Actually 2 power supplies Maybe not shared GND. Good point !
EDIT. Connected gnd no change. Shielded cable 8” no change, lots of bad values, 80% good values but random very big positive also negative numbers make our go crazy. Using my go to old school 4port FDS from 10+ years ago.
With ping-pong multi-tasking the normal FDS is only reliable for 115200 baud -- seems like using a 4-port serial object could be the reason for the speed issue.
96000 is working so this is close enough for this type of test streaming a Long signed value. Adding any method to do error checking will add more time. A simple method could be sum the 4 bytes and send the sum (or inverted sum) as a 5th byte. Then parse the 4 bytes into Long in receive, add 4 bytes invert and compare with byte 5. If bad compare then ignore the packet. Other compact methods to check the packet ?
@Mickster said:
T Chap and I are doing similar stuff and one of the really neat things about using the LS7366R device; it is SPI and has it's own 5V UPS to keep the device + encoder alive during power-down (it also features a lost-power flag in case the UPS dies). Re-homing a machine can be a royal PITA. This way, the machine can be powered-up in a morning and ready-to-roll. Should any of the axes get disturbed during power-down, no problem because the 7366 keeps counting - effectively, an absolute encoder. Furthermore, in my case, the encoder counting rate needs to be way more than the P1 can handle. The 7366 is good for 40M counts/sec when using differential receivers. I seem to remember that T Chap's encoders are open collector so not true in his case but still way faster than the P1 can handle. I'm doing similar but I have substituted a RPi Pico for the 7366. I can have the Pico on a UPS and handle 4 encoders at high-ish count-rates. OTOH, if the P1 is fast enough for T Chap, he could have a UPS-backed P1, dedicated to simply reading 3 encoders and banging-out the 3 longs, serially. On power-up, the main P1 just starts RX-ing the 3 longs.
Another mid-point-solution for P1 quad counting, could be to use two P1 counters and take the difference. (both count up)
A quick look has 2 logic chips needed : 1 x TI 74HCS86 (or similar Schmitt XOR from Diodes inc or Nexperia) and 1 x 74HC153, to give QUAD to CLK_UP, CLK_DN signals.
Speed would be well above SW, and should easily give > 10MHz edge rates.
@"T Chap" said:
Edit. Drift is not io pins. I changed boards. It is not obvious in a scope. Wires are 8” unshielded. At very slow speeds this should not be happening.
Bottom line is this seems like a bonafide method to connect to an external PID over Quad, but for sure will have some error checking behind the scenes over to be sure there is no drift.
That seems strange.
What was the receiver here ?
Another link choice for local data, could be a variant of the SENT bus ? (Single edge nibble transfer)
That nibble encodes data with a fixed HI time for autobaud/sync and then a 16 step OFF time for data, so is well suited to P1 timers.
If both P1 run crystals, more than 4 bits could be sent for every edge-pair.
Thanks for your input jmg. I created a quad output simulator on one p1 board. It is extremely simple. It counts up to x and counts back down. You can change the delay between transitions from max spin repeat frequency to any slower rate. The receiver is both jonnymac encoder engine and the classic rotary encoder engine. Both of which I use on tons of projects with motors with encoders that would never tolerate drift. This is a mystery. Testing tonight positive counts at 100 repeats in spin. Pause 1 sec. Keep repeating this and it looses a number every so many cycles. It seems like it the stopping for 1 second that may be where is error is occurring
Another mid-point-solution for P1 quad counting, could be to use two P1 counters and take the difference. (both count up)
A quick look has 2 logic chips needed : 1 x TI 74HCS86 (or similar Schmitt XOR from Diodes inc or Nexperia) and 1 x 74HC153, to give QUAD to CLK_UP, CLK_DN signals.
Speed would be well above SW, and should easily give > 10MHz edge rates.
Have wanted to do this since forever but this dumba$$ just can't get a handle on rollover (which will happen PDQ). I have laid numbers out, used calculators, scoured the web...never got to grips with an elegant, seamless solution.
For an external hardware solution, I just grab a RPi Pico and bang the four encoder counts out via UART@921.6K-Baud. Alternatively, these things are easily I2C slaves:
PicoMite BASIC, BTW.
'Quadrature multichannel decoder for PicoMite using PIO
'this is a 4 channel quadrature decoder for MMBasic V5.08.00 or newer
'running on a PicoMite or PicoMiteVGA usinf PIO 1
'program PIO 1
program_PIO 'program the code in PIO 1
'quadrature decoders generic settings
PIO_f%=63e6 'frequency = 63MHz
PIO_s%=0 'shift register (shift in left)
PIO_e%=PIO(execctrl gp0,wrp_tgt,wrap) 'start and stop of the loop
'start quadrature decoders (uncomment the needed decoders)
start_sm0 : sm0=1 'start decoder on GP0 and GP1
'start_sm1 : sm1=1 'start decoder on GP2 and GP3
'start_sm2 : sm2=1 'start decoder on GP4 and GP5
'start_sm3 : sm3=1 'start decoder on GP26 and GP27
'this code is just a demo that shows the position of the quadrature decoders
'the selected decoder positions are printed on the console
'type "r" to reset the decoders to 0
'main loop
do
a$=inkey$ 'just for control
'get the data from the fifo and print
if sm0 then print str$(read_fifo(0),12,0); 'get data from decoder
if sm1 then print str$(read_fifo(1),12,0); 'get data from decoder
if sm2 then print str$(read_fifo(2),12,0); 'get data from decoder
if sm3 then print str$(read_fifo(3),12,0); 'get data from decoder
print
'just some pause
pause 100 'any delay needed
'reset position (PIO X register) under control of keyboard
if a$="r" then 'press r to zero position
if sm0 then pio execute 1,0,&hA023 '= assembly "mov X, null" (zero X reg)
if sm1 then pio execute 1,1,&hA023 '= assembly "mov X, null" (zero X reg)
if sm2 then pio execute 1,2,&hA023 '= assembly "mov X, null" (zero X reg)
if sm3 then pio execute 1,3,&hA023 '= assembly "mov X, null" (zero X reg)
a$=""
end if
'this function returns the actual count of decoder n
function read_fifo(n) as integer
local dat%(3)
pio read 1,n,4,dat%() 'read whole fifo
read_fifo = dat%(3) 'last data in fifo
if read_fifo>2147483647 then inc read_fifo,-4294967296 '2'th complement
end function
'this subroutine programs the quadrature decoder program for PIO1 into
'PIO program memory
sub program_PIO
'this is the PIO program in machine code
dim p%(7)=(&h001A00170015001A,&h0015001A001A0017,&h0017001A001A0015, &h001A00150017001A,&h4042A0404042A0C3,&hA029001A005AA0A6,&h8000A0C1A0290059,0)
'here the program is programmed in memory
pio program 1,p%()
wrap=27 'end of the program
wrp_tgt=16 'start of the program loop
end sub
'this subroutine starts state machine 0 quadrature decoder on gp0 and gp1
sub start_sm0
'uses GP0,GP1, assign pins in MMBasic
setpin gp0,pio1
setpin gp1,pio1
'assign pins in PIO
pin_sm0%=PIO(pinctrl 0,0,0,gp0)
'configure and start PIO
pio init machine 1,0,PIO_f%,pin_sm0%,PIO_e%,PIO_s%,wrp_tgt
pio start 1,0
end sub
'this subroutine starts state machine 1 quadrature decoder on gp2 and gp3
sub start_sm1
'uses GP2,GP3, assign pins in MMBasic
setpin gp2,pio1
setpin gp3,pio1
'assign pins in PIO
pin_sm1%=PIO(pinctrl 0,0,0,gp2)
'configure and start PIO
pio init machine 1,1,PIO_f%,pin_sm1%,PIO_e%,PIO_s%,wrp_tgt
pio start 1,1
end sub
'this subroutine starts state machine 2 quadrature decoder on gp4 and gp5
sub start_sm2
'uses GP4,GP5, assign pins in MMBasic
setpin gp4,pio1
setpin gp5,pio1
'assign pins in PIO
pin_sm2%=PIO(pinctrl 0,0,0,gp4)
'configure and start PIO
pio init machine 1,2,PIO_f%,pin_sm2%,PIO_e%,PIO_s%,wrp_tgt
pio start 1,2
end sub
'this subroutine starts state machine 3 quadrature decoder on gp26 and gp27
sub start_sm3
'uses GP26,GP27, assign pins in MMBasic
setpin gp26,pio1
setpin gp27,pio1
'assign pins in PIO
pin_sm3%=PIO(pinctrl 0,0,0,gp26)
'configure and start PIO
pio init machine 1,3,PIO_f%,pin_sm3%,PIO_e%,PIO_s%,wrp_tgt
pio start 1,3
@"T Chap" said:
Thanks for your input jmg. I created a quad output simulator on one p1 board. It is extremely simple. It counts up to x and counts back down. You can change the delay between transitions from max spin repeat frequency to any slower rate. The receiver is both jonnymac encoder engine and the classic rotary encoder engine. Both of which I use on tons of projects with motors with encoders that would never tolerate drift. This is a mystery. Testing tonight positive counts at 100 repeats in spin. Pause 1 sec. Keep repeating this and it looses a number every so many cycles. It seems like it the stopping for 1 second that may be where is error is occurring
every 100 repeats or maybe every xx seconds cnt overflow?
Another mid-point-solution for P1 quad counting, could be to use two P1 counters and take the difference. (both count up)
A quick look has 2 logic chips needed : 1 x TI 74HCS86 (or similar Schmitt XOR from Diodes inc or Nexperia) and 1 x 74HC153, to give QUAD to CLK_UP, CLK_DN signals.
Speed would be well above SW, and should easily give > 10MHz edge rates.
Have wanted to do this since forever but this dumba$$ just can't get a handle on rollover (which will happen PDQ). I have laid numbers out, used calculators, scoured the web...never got to grips with an elegant, seamless solution.
I think you just treat it like a clock with two hour hands and take the least-distance.
That does cost you one bit, so max is 2^31, or you can extend the counters in SW for a 2^63 limit.
For an external hardware solution, I just grab a RPi Pico and bang the four encoder counts out via UART@921.6K-Baud. Alternatively, these things are easily I2C slaves:
Yes, the PIO on those is nifty. There is chatter about a new RP2040, but nothing concrete yet.
There is no specific pattern. The drift is random but every few cycles. My Quad output simulator on p1 is very slow compared to real encoder projects that don’t drift. One test today the scope shows 500hz on the A channel. Yet 5k cycles on a motor with encoder never drifts so I am not pushing the speed limits. I’ve tried various boards that work fine on real encoders. This has to be my quad simulator code. But quad output is as simple as it gets. Hoping for an a ha moment soon.
@msrobots said:
@"T Chap" said:
Thanks for your input jmg. I created a quad output simulator on one p1 board. It is extremely simple. It counts up to x and counts back down. You can change the delay between transitions from max spin repeat frequency to any slower rate. The receiver is both jonnymac encoder engine and the classic rotary encoder engine. Both of which I use on tons of projects with motors with encoders that would never tolerate drift. This is a mystery. Testing tonight positive counts at 100 repeats in spin. Pause 1 sec. Keep repeating this and it looses a number every so many cycles. It seems like it the stopping for 1 second that may be where is error is occurring
every 100 repeats or maybe every xx seconds cnt overflow?
There has to be some artifact happening in this quad send test code. Count up to 10,100,1000,2000 then back down. It doesnt matter how high you count up or down, the drift is 2 or rarely 4. 3 good cycles, 1 bad. Or you can see bad, bad, bad, good, bad, good good.
Pub SimulateQuad
dira[3..4] := %11
' FORWARD
QuadState := 1
Repeat
Repeat 100
QuadState++
If QuadState > 4 ' reset upper
QuadState := 1
Elseif QuadState < 1 ' reset lower
QuadState := 4
OutputQuad
w(1_000_000) ' Set repeat Frequeny
w(80_000_000) ' wait at end of count up down
' REVERSE
Repeat 100
QuadState--
If QuadState > 4 ' reset upper
QuadState := 1
Elseif QuadState < 1 ' reset lower
QuadState := 4
OutputQuad
w(1_000_000) ' Set repeat Frequeny
w(80_000_000) ' wait at end of count up down
PUB OutputQuad
Case QuadState
1 : outa[3..4] := %00
2 : outa[3..4] := %10
3 : outa[3..4] := %11
4 : outa[3..4] := %01
@"T Chap" said:
There is no specific pattern. The drift is random but every few cycles. My Quad output simulator on p1 is very slow compared to real encoder projects that don’t drift. One test today the scope shows 500hz on the A channel. Yet 5k cycles on a motor with encoder never drifts so I am not pushing the speed limits. I’ve tried various boards that work fine on real encoders. This has to be my quad simulator code. But quad output is as simple as it gets. Hoping for an a ha moment soon.
It would need some sort of runt pulse, that the decoder only managed to track one edge of, but the code looks fine.
Could anything else be disturbing the pins ?
Because it is slow, you could add some RC+Schmitt filters, to see if that solves the drift/creep ?
@"T Chap" said:
There has to be some artifact happening in this quad send test code. Count up to 10,100,1000,2000 then back down. It doesnt matter how high you count up or down, the drift is 2 or rarely 4. 3 good cycles, 1 bad. Or you can see bad, bad, bad, good, bad, good good.
The code does not start in a defined state, but that should only give 1 edge error ? (depends a bit on how a possible illegal 00-11 or 11-00 is handled)
Also check the pins are not floating before the run starts.
You could try starting from a known state, (reset the slave after POR and before run) and check if cycling mod 4 sizes changes the effect ( ie hand overs are then always the same phase)
470 ohm in series on both A and B instantly cured it, many various tests and repeat values and zero failures.
I think this was ringing. The P1 on the receive side had 10k pulldowns already. The 470 cleaned up the scope where I saw typical spikes on occasional transitions which can be normal for adjacent line crossing over with signals.
Thanks for all the suggestions.
I agree Schm Triggers would benefit, I use those on all motor encoder inputs to P1.
Back to the original point, I think the quad method of steaming positions is a good solution to my separation of profile generator and PID engine. Looking forward to getting back to testing that tomorrow. One quad pulse replaces for 4 bytes of position data. The code can do a periodic sanity check to verify position values between boards.
With one P1 board running the Quad output simulator over 8" wires to another P1 board with a Quad receive loop. Ran 16 hours overnight a loop counting up to 100 then back down in repeat, in spin a waitcnt of 10_000 after each Quad pulse output. Saw a drift of 2. Then set to no wait, as fast as spin can loop and change the outputs, and count to 1000 then back down in a loop. 6 hours no drift.
@"T Chap" said:
470 ohm in series on both A and B instantly cured it, many various tests and repeat values and zero failures.
I think this was ringing. The P1 on the receive side had 10k pulldowns already. The 470 cleaned up the scope where I saw typical spikes on occasional transitions which can be normal for adjacent line crossing over with signals.
Seems a little bit sensitive ?
I like to place RC+Schmitt, where the RC filter+hyst is chosen so the narrowest pulse possible, is always wide enough to catch both edges.
However, software should be able to get close, with the care of single-point sampling and follow ? like this psuedo code
Qx = Qpin XOR Qo // single point sample
QCtr = QCtr + DiffTable[(Qx << 2) + Qo] // 16 entry table +1/-1/0
Qo = Qo XOR Qx // update Qo, using single point sample.
Here even a glitch will update Qo, so the next pass thru does a balanced INC/DEC
Comments
Odd behavior for sure. I need to do some more experiments. At very low speeds this should not be noise. I question if transitions out of the prop using outa[3..4] := %11 etc are valid methods for this type of quad output. I like the quadrature concept and it is faster to send quad than 4+ serial bytes. I tested today sending 4 bytes as position over 8” wires. 155k baud didn’t work. 80k works. But it is slower to create and read the packets in spin. I discovered that instead of the profile generator updating position at +1 per iteration I tried +2 per iteration on my test board sending the positions and that creates a faster motor speed without needing to run the data stream. The proof of concept is working out nicely to park 3 profile generators in one main board prop and stream positions to 3 sub boards running PID.
Something not right with this. Common gnd?
Been a while since I looked but I seem to remember that FDS (probably others) handles the binary-2-string / string-2-binary, internally, no?
Craig
Well that’s a good question. I am using
Serial.tx(position.byte[0]
Serial.tx(position.byte[1]
Serial.tx(position.byte[2]
Serial.tx(position.byte[3]
And receive side
Outa[4]~~ ‘tell sender to send another packet
Serial.rx. ‘ wait for first byte
Serial.rxtime(10)
Serial.rxtime(10)
Serial.rxtime(10)
Outa[4]~ ‘tell sender to not send anymore
Position = Add 4 bytes together bit shifting each byte
Maybe there is a better way!
I’ll check the GND between both boards. Actually 2 power supplies Maybe not shared GND. Good point !
EDIT. Connected gnd no change. Shielded cable 8” no change, lots of bad values, 80% good values but random very big positive also negative numbers make our go crazy. Using my go to old school 4port FDS from 10+ years ago.
With ping-pong multi-tasking the normal FDS is only reliable for 115200 baud -- seems like using a 4-port serial object could be the reason for the speed issue.
96000 is working so this is close enough for this type of test streaming a Long signed value. Adding any method to do error checking will add more time. A simple method could be sum the 4 bytes and send the sum (or inverted sum) as a 5th byte. Then parse the 4 bytes into Long in receive, add 4 bytes invert and compare with byte 5. If bad compare then ignore the packet. Other compact methods to check the packet ?
Checksum alternative: subsequent updates should be within reason. Quicker to do this check?
Packet: From one update to the next, 16 bits should be more than enough. Halve the packet size?
Craig
Another mid-point-solution for P1 quad counting, could be to use two P1 counters and take the difference. (both count up)
A quick look has 2 logic chips needed : 1 x TI 74HCS86 (or similar Schmitt XOR from Diodes inc or Nexperia) and 1 x 74HC153, to give QUAD to CLK_UP, CLK_DN signals.
Speed would be well above SW, and should easily give > 10MHz edge rates.
That seems strange.
What was the receiver here ?
Another link choice for local data, could be a variant of the SENT bus ? (Single edge nibble transfer)
That nibble encodes data with a fixed HI time for autobaud/sync and then a 16 step OFF time for data, so is well suited to P1 timers.
If both P1 run crystals, more than 4 bits could be sent for every edge-pair.
Thanks for your input jmg. I created a quad output simulator on one p1 board. It is extremely simple. It counts up to x and counts back down. You can change the delay between transitions from max spin repeat frequency to any slower rate. The receiver is both jonnymac encoder engine and the classic rotary encoder engine. Both of which I use on tons of projects with motors with encoders that would never tolerate drift. This is a mystery. Testing tonight positive counts at 100 repeats in spin. Pause 1 sec. Keep repeating this and it looses a number every so many cycles. It seems like it the stopping for 1 second that may be where is error is occurring
Have wanted to do this since forever but this dumba$$ just can't get a handle on rollover (which will happen PDQ). I have laid numbers out, used calculators, scoured the web...never got to grips with an elegant, seamless solution.
For an external hardware solution, I just grab a RPi Pico and bang the four encoder counts out via UART@921.6K-Baud. Alternatively, these things are easily I2C slaves:
PicoMite BASIC, BTW.
Craig
every 100 repeats or maybe every xx seconds cnt overflow?
I think you just treat it like a clock with two hour hands and take the least-distance.
That does cost you one bit, so max is 2^31, or you can extend the counters in SW for a 2^63 limit.
Yes, the PIO on those is nifty. There is chatter about a new RP2040, but nothing concrete yet.
There is no specific pattern. The drift is random but every few cycles. My Quad output simulator on p1 is very slow compared to real encoder projects that don’t drift. One test today the scope shows 500hz on the A channel. Yet 5k cycles on a motor with encoder never drifts so I am not pushing the speed limits. I’ve tried various boards that work fine on real encoders. This has to be my quad simulator code. But quad output is as simple as it gets. Hoping for an a ha moment soon.
There has to be some artifact happening in this quad send test code. Count up to 10,100,1000,2000 then back down. It doesnt matter how high you count up or down, the drift is 2 or rarely 4. 3 good cycles, 1 bad. Or you can see bad, bad, bad, good, bad, good good.
It would need some sort of runt pulse, that the decoder only managed to track one edge of, but the code looks fine.
Could anything else be disturbing the pins ?
Because it is slow, you could add some RC+Schmitt filters, to see if that solves the drift/creep ?
The code does not start in a defined state, but that should only give 1 edge error ? (depends a bit on how a possible illegal 00-11 or 11-00 is handled)
Also check the pins are not floating before the run starts.
You could try starting from a known state, (reset the slave after POR and before run) and check if cycling mod 4 sizes changes the effect ( ie hand overs are then always the same phase)
Seems to be solved.
470 ohm in series on both A and B instantly cured it, many various tests and repeat values and zero failures.
I think this was ringing. The P1 on the receive side had 10k pulldowns already. The 470 cleaned up the scope where I saw typical spikes on occasional transitions which can be normal for adjacent line crossing over with signals.
Thanks for all the suggestions.
I agree Schm Triggers would benefit, I use those on all motor encoder inputs to P1.
Back to the original point, I think the quad method of steaming positions is a good solution to my separation of profile generator and PID engine. Looking forward to getting back to testing that tomorrow. One quad pulse replaces for 4 bytes of position data. The code can do a periodic sanity check to verify position values between boards.
With one P1 board running the Quad output simulator over 8" wires to another P1 board with a Quad receive loop. Ran 16 hours overnight a loop counting up to 100 then back down in repeat, in spin a waitcnt of 10_000 after each Quad pulse output. Saw a drift of 2. Then set to no wait, as fast as spin can loop and change the outputs, and count to 1000 then back down in a loop. 6 hours no drift.
Seems a little bit sensitive ?
I like to place RC+Schmitt, where the RC filter+hyst is chosen so the narrowest pulse possible, is always wide enough to catch both edges.
However, software should be able to get close, with the care of single-point sampling and follow ? like this psuedo code
Here even a glitch will update Qo, so the next pass thru does a balanced INC/DEC
Yes. Messed-up encoder data can be quite spectacular (read: expensive)
I have always used differential signals, feeding a MC3486. This is Yaskawa:
Craig