Home
JAQForum Ver 24.01
Log In or Join  
Active Topics
Local Time 17:50 25 Nov 2024 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : PIO for quadrature encoders

     Page 3 of 4    
Author Message
Mixtel90

Guru

Joined: 05/10/2019
Location: United Kingdom
Posts: 6783
Posted: 11:42am 30 Apr 2024
Copy link to clipboard 
Print this post

The PIO devices are effectively processors in their own right. They have nothing to do with the CPU cores unless you are transferring data to or from them. They can even handle their own GPIO pins.

On top of that, each of the four state machines in each PIO can also runs relatively independently, although the program space is a bit limited. You can still have, say, 3 state machines running one program and the fourth running a different program.

I don't know who thought these PIOs up, but it's a brilliant idea. :)
Mick

Zilog Inside! nascom.info for Nascom & Gemini
Preliminary MMBasic docs & my PCB designs
 
PhenixRising
Guru

Joined: 07/11/2023
Location: United Kingdom
Posts: 857
Posted: 02:10pm 30 Apr 2024
Copy link to clipboard 
Print this post

@Mick
  Quote  I don't know who thought these PIOs up, but it's a brilliant idea. :)

No kidding  


@Volhout
Not an issue but just curious as to how/why 32 hex values are printed when starting the PIO code? Not being printed by MMBasic.

  Quote  
0: 001A
1: 0015
2: 0017
3: 001A
4: 0017
5: 001A
6: 001A
7: 0015
8: 0015
9: 001A
10: 001A, etc.
 
Volhout
Guru

Joined: 05/03/2018
Location: Netherlands
Posts: 4225
Posted: 02:30pm 30 Apr 2024
Copy link to clipboard 
Print this post

Hi Phenix,

See here for an explanation:

Bug in assembler

It seems like the assembler only writes the PIO code into memory when you use the option "list". And option list shows a list of the PIO program in hexadecimal form.
Without list...no program. I am sure Peter will fix this soon, but he is at the moment not able to fix bugs. Patience...

Volhout
PicomiteVGA PETSCII ROBOTS
 
Volhout
Guru

Joined: 05/03/2018
Location: Netherlands
Posts: 4225
Posted: 02:32pm 30 Apr 2024
Copy link to clipboard 
Print this post

  Mixtel90 said  The PIO devices are effectively processors in their own right. They have nothing to do with the CPU cores unless you are transferring data to or from them. They can even handle their own GPIO pins.

On top of that, each of the four state machines in each PIO can also runs relatively independently, although the program space is a bit limited. You can still have, say, 3 state machines running one program and the fourth running a different program.

I don't know who thought these PIOs up, but it's a brilliant idea. :)


Hi Mick,

It is not only the PIO's that are brilliant. Actually this piece of PIO code, with the JMP table, is also a brilliant idea.

Volhout
PicomiteVGA PETSCII ROBOTS
 
Volhout
Guru

Joined: 05/03/2018
Location: Netherlands
Posts: 4225
Posted: 08:20pm 30 Apr 2024
Copy link to clipboard 
Print this post

Hi Phenix,

This is the code for up to 4 decoders.
The MMBasic PIO assembler is not used in this code, since the PIO code is mature.
I hope the code is self-explanatory

 '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
 
 'Original PIO source: https://github.com/p-o-l-e/quadrature-decoder
 
 '30-4-2024  Volhout
 
 
 
 'system initialisation ---------------------------------------------------------
 
 '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
 
 
 
 'main MMBasic code -------------------------------------------------------------
 
 '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
   
 loop while a$=""  'exit when any key not r
 
end
 
 
 
 
 ' subroutines -------------------------------------------------------------------

 
 '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
 
end sub

PicomiteVGA PETSCII ROBOTS
 
PhenixRising
Guru

Joined: 07/11/2023
Location: United Kingdom
Posts: 857
Posted: 08:35pm 30 Apr 2024
Copy link to clipboard 
Print this post

Oh fantastic..THANK YOU

Tomorrow, I'll hook-up a slave encoder and test the electronic gearing  
 
PhenixRising
Guru

Joined: 07/11/2023
Location: United Kingdom
Posts: 857
Posted: 02:02pm 01 May 2024
Copy link to clipboard 
Print this post

Hey Harm,

This is working beautifully  

Spend as much as you want on a Siemens S7-1500 but it still won't do this  
 
Volhout
Guru

Joined: 05/03/2018
Location: Netherlands
Posts: 4225
Posted: 09:54am 02 May 2024
Copy link to clipboard 
Print this post

  PhenixRising said  
Spend as much as you want on a Siemens S7-1500 but it still won't do this  

Phenix,

That is a firm statement. But remember the S7 is a system, that may have an inferior motor controller, for much money, but it is more than just that.

So now you have the building blocks to make an even greater system. I am very curious to see your system growing, so keep us informed.

Always willing to help,

Volhout
PicomiteVGA PETSCII ROBOTS
 
PhenixRising
Guru

Joined: 07/11/2023
Location: United Kingdom
Posts: 857
Posted: 10:40am 02 May 2024
Copy link to clipboard 
Print this post

@Volhout

I have been severely punishing this system to verify the integrity of the encoder count...absolutely solid

There is a 3rd encoder channel which is the index pulse, used for precise "homing".
The pulse only occurs one time/revolution. I have it tied to an input-interrupt which captures the count.
Naturally, this is only useable at very low speeds but it's perfect for checking for lost encoder counts.

A future enhancement might be for the PIO to latch a pre-loaded register to set the counter to a predetermined value when the index signal happens?



Pre_load_value = [32bit INT]

Arm_the_PIO_index_latch

Move_the_motor_until_index_pulse_occurs

Transfer_Pre_load_value_to_PIO_count_register



I am accustomed to 1KHz/2KHz/4KHz PID sample rates but I notice that many machine controllers use 250Hz or lower.
I have been experimenting with 250Hz and it's perfectly smooth and very responsive.

Once I eliminate the slow PWM and switch to an external DAC, a single Pico should be able to handle 4 high-performance axes with ease.


You made this a wonderful week for me, Harm  
 
Volhout
Guru

Joined: 05/03/2018
Location: Netherlands
Posts: 4225
Posted: 01:51pm 02 May 2024
Copy link to clipboard 
Print this post

Hi Phenix,

Setting X to a pre-defined value does not require any changes to the PIO program.
You have to perform 3 actions:

1/ write the desired count to the TX FIFO
2/ force the PIO to read the TX FIFO into the Output Shift Register (OSR) with a direct command
3/ force the PIO to copy the OSR value into the X register with a direct command. This direct command does the actual update. 1/ and 2/ are not time critical. But it is best to execute 3/ when the decoder is not actively counting (motor halted).

Example code (tested in the single decoder program).

   'set defined position in register X under control of the keyboard
   if a$="s" then
     input "desired count ";cnt%
     pio write 1,0,1,cnt%       'write the count cnt% in the fifo
     pio execute 1,0,&h8080  '= assemble "pull" (moves FIFO to OSR register)
     PIO execute 1,0,&hA027  '= assemble "mov X, OSR" moves the OSR value to X
     a$=""
   end if


Volhout
PicomiteVGA PETSCII ROBOTS
 
PhenixRising
Guru

Joined: 07/11/2023
Location: United Kingdom
Posts: 857
Posted: 03:40pm 15 May 2024
Copy link to clipboard 
Print this post

  Volhout said  Hi Phenix,

Setting X to a pre-defined value does not require any changes to the PIO program.
You have to perform 3 actions:

1/ write the desired count to the TX FIFO
2/ force the PIO to read the TX FIFO into the Output Shift Register (OSR) with a direct command
3/ force the PIO to copy the OSR value into the X register with a direct command. This direct command does the actual update. 1/ and 2/ are not time critical. But it is best to execute 3/ when the decoder is not actively counting (motor halted).

Example code (tested in the single decoder program).

   'set defined position in register X under control of the keyboard
   if a$="s" then
     input "desired count ";cnt%
     pio write 1,0,1,cnt%       'write the count cnt% in the fifo
     pio execute 1,0,&h8080  '= assemble "pull" (moves FIFO to OSR register)
     PIO execute 1,0,&hA027  '= assemble "mov X, OSR" moves the OSR value to X
     a$=""
   end if


Volhout



Hey Harm,

The above has been working beautifully, until...I just tried a cnt% < 0 and with it being a 64bit integer, the system doesn't like it.

If I force-feed it &hFFFFFC18, I get the expected -1000D but the 64bit version, I get a crash & burn.
 
Mixtel90

Guru

Joined: 05/10/2019
Location: United Kingdom
Posts: 6783
Posted: 04:43pm 15 May 2024
Copy link to clipboard 
Print this post

As a RAF doctor once told my dad, "If it hurts that much then don't do it". :)
(It may be only a story!)
Mick

Zilog Inside! nascom.info for Nascom & Gemini
Preliminary MMBasic docs & my PCB designs
 
Volhout
Guru

Joined: 05/03/2018
Location: Netherlands
Posts: 4225
Posted: 04:59pm 15 May 2024
Copy link to clipboard 
Print this post

The fifo is 32 bit.so you would need a 32 bit value.
But unless you write float to the fifo, that would not matter I guess. It would just mask off the 32 most significant bits. I guess…

Volhout
Edited 2024-05-16 03:03 by Volhout
PicomiteVGA PETSCII ROBOTS
 
PhenixRising
Guru

Joined: 07/11/2023
Location: United Kingdom
Posts: 857
Posted: 06:14pm 15 May 2024
Copy link to clipboard 
Print this post

@Volhout

Yeah I thought that this should work:


axval="-500"
tststr=bin2str$(int32,val(axval),big)
pio write 1,0,1,str2bin(int32,tststr,BIG)


But this is what I get:
  Quote  
[270] PIO write 1,0,1,Str2bin(int32,tststr,BIG)
Error : -550 is invalid (valid is 0 to -1)


Any value => 0 works fine  
 
PhenixRising
Guru

Joined: 07/11/2023
Location: United Kingdom
Posts: 857
Posted: 06:36pm 15 May 2024
Copy link to clipboard 
Print this post

Forgot to mention that this works fine:


pio write 1,0,1,&hFFFFFDDA


I get -550
 
Volhout
Guru

Joined: 05/03/2018
Location: Netherlands
Posts: 4225
Posted: 06:44pm 15 May 2024
Copy link to clipboard 
Print this post

Hi Phenix,

This works for me

'set defined position in register X under control of the keyboard
  if a$="s" then
    input "desired count ";cnt%
    cnt%=cnt% and &hffffffff   'concatenate to 32 bits
    pio write 1,0,1,cnt%       'write the count cnt% in the fifo
    pio execute 1,0,&h8080     '= assemble "pull" (moves FIFO to OSR register)
    PIO execute 1,0,&hA027     '= assemble "mov X, OSR" moves the OSR value to X
    a$=""
  end if


Volhout
Edited 2024-05-16 04:46 by Volhout
PicomiteVGA PETSCII ROBOTS
 
PhenixRising
Guru

Joined: 07/11/2023
Location: United Kingdom
Posts: 857
Posted: 07:29pm 15 May 2024
Copy link to clipboard 
Print this post

@Volhout

Man, I must totally suck

I mask all the time and was absolutely sure I tried this

Works perfectly. Many, many thanks again.

Now, where did I put that job-application for McDonalds  
 
PhenixRising
Guru

Joined: 07/11/2023
Location: United Kingdom
Posts: 857
Posted: 08:50am 24 May 2024
Copy link to clipboard 
Print this post

Hey Harm  

Just an FYI; there appears to be some kind of pipeline thing happening.

This is new territory, for me, in that; I'm experimenting with a low-ish sample-rate of 250Hz. Drove me crazy for awhile because I was observing motor overshoot (albeit very small) at the end of deceleration. No amount of PID tuning would eliminate it but then I discovered that my position reading was one-sample behind.

I went from a single read
  Quote  
  'get the data from the fifo
  pio read 1,0,4,dat%()                         'read whole fifo
  posi=dat%(3)                                  'last data in fifo
  if posi>2147483647 then inc posi,-4294967296  '2'th complement
  print posi


To a double read
  Quote  
  'get the data from the fifo
  pio read 1,0,4,dat%()                         'read whole fifo
  pio read 1,0,4,dat%()                         'read whole fifo
  posi=dat%(3)                                  'last data in fifo
  if posi>2147483647 then inc posi,-4294967296  '2'th complement
  print posi


Beautiful...no more overshoot  
 
Volhout
Guru

Joined: 05/03/2018
Location: Netherlands
Posts: 4225
Posted: 09:27am 24 May 2024
Copy link to clipboard 
Print this post

Hi Phenix,

Yes, I have seen this before, in my SSTV decoder, and there it was sufficient to read only 1 sample extra. So the 4 in the FIFO, and the 5'th being on it's ways from X to ISR to FIFO.

So if you make the data array 1 larger.
DIM dat%(4)


Then read 5 (not 4) from the FIFO, and use the 5'th value in the array.
PIO READ 1,0,5,dat%()
posi=dat%(4)


You should be fine too...

Volhout
Edited 2024-05-24 19:27 by Volhout
PicomiteVGA PETSCII ROBOTS
 
PhenixRising
Guru

Joined: 07/11/2023
Location: United Kingdom
Posts: 857
Posted: 01:57pm 25 May 2024
Copy link to clipboard 
Print this post

Hi Harm,

Works great, thanks again  


I have a machine on the way, it's gonna be the first all-PicoMite controlled. Yaskawa motors feature 17bit Encoders  
A good test for the PIO



PicoMites to replace obsolete OMRON and Rexroth motion controllers plus the PLC
Profibus is also history.



Loaded-up in Ireland, yesterday.


No summer for me  
 
     Page 3 of 4    
Print this page
© JAQ Software 2024