Home
JAQForum Ver 24.01
Log In or Join  
Active Topics
Local Time 23:56 27 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 : SetPin(GPnn), FIN query

     Page 1 of 2    
Author Message
carlschneider
Senior Member

Joined: 04/08/2023
Location: South Africa
Posts: 158
Posted: 01:12am 26 Aug 2023
Copy link to clipboard 
Print this post

Hi there

I note that currently Pin(GPnn), FIN returns an integer value.

Is this correct or am I missing something?

I'm looking to measure a frequency of 50Hz to at least 3 decimal places.

Any guidance would be appreciated.
Cheers Carl                                                        
Retirement is tough on Hobbies without a day job
 
Chopperp

Guru

Joined: 03/01/2018
Location: Australia
Posts: 1057
Posted: 02:01am 26 Aug 2023
Copy link to clipboard 
Print this post

Hi Carl

As far as I know, it is the nature of the beast. so to speak.
You will only get integers with MMBasic, even if you use a longer gate time
(but I could be wrong)

  From the Manual
SETPIN pin, cfg [, option]

FIN Frequency input
 'option' can be used to specify the gate time (the length of time
 used to count the input cycles). It can be any number between 10
 ms and 100000 ms. Note that the PIN() function will always return the frequency
correctly scaled in Hz regardless of the gate  time used. If 'option' is omitted the gate time will be 1 second.

Brian
Edited 2023-08-26 12:19 by Chopperp
ChopperP
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 6100
Posted: 03:26am 26 Aug 2023
Copy link to clipboard 
Print this post

Measure period and invert for low frequencies.

Jim
VK7JH
MMedit   MMBasic Help
 
carlschneider
Senior Member

Joined: 04/08/2023
Location: South Africa
Posts: 158
Posted: 03:43am 26 Aug 2023
Copy link to clipboard 
Print this post

Thanks for the feedback @chopperp and TassyJim.

I have tried longer gate periods but the result is always an integer value, even printing str$(pin(GPnn),6,4).

I have used PULSIN to measure the period and using that to determined the frequency. It measures period in µs.


Sub Freq
TimeEnd=Timer
Period%=Pulsin(GP22,0,25000,25000)
Period2%=Pulsin(GP22,0,25000,25000)
Period3%=Pulsin(GP22,0,25000,25000)
Period%=(Period3%+Period%+Period2%)/3
DeltaTime=TimeEnd-TimeStart
Freq!=(1000000/Period%)/2 ' Measuring PWM 50% duty cycle so two edges
Frequency$=Str$(Freq!,6,2) ' used in the JSON string to talk to the graph
TimeStart=Timer
End Sub


This subroutine is called by a 1s Tick. Interestingly the DeltaTime is rarely 1000ms, usually under.



Frequency to 2 decimal places. Target frequency for the PWM output I'm measuring is 50.01Hz.




Using the Pin(GPNN),FIN would just have been far more elegant:)
Edited 2023-08-26 13:47 by carlschneider
Cheers Carl                                                        
Retirement is tough on Hobbies without a day job
 
phil99

Guru

Joined: 11/02/2018
Location: Australia
Posts: 2136
Posted: 07:41am 26 Aug 2023
Copy link to clipboard 
Print this post

As TassyJim says, it's slow but it works.
> setpin gp7,fin,10000
> do : ? pin(gp7) : pause 10000 : loop
25
50
60.7
67
69.5
69.5
63.7
50
50
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 9126
Posted: 07:54am 26 Aug 2023
Copy link to clipboard 
Print this post

  Quote  I note that currently Pin(GPnn), FIN returns an integer value.


It returns a floating point number but this is derived as the number of counts in 1000mSec (default) like any other frequency counter. so 50 counts in 1000 mSec gives a frequency of 50. Can't be anything but an integer in this case.If you set the gate time to 2 seconds and there are 101 counts in the period then you will get a frequency of 50.5.
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 6100
Posted: 08:22am 26 Aug 2023
Copy link to clipboard 
Print this post

If you are serious about high resolution, get a GPS with 1Hz output and measure the change in phase between it and the 50Hz.

I did that successfully a few years ago, just for fun.

Jim
VK7JH
MMedit   MMBasic Help
 
carlschneider
Senior Member

Joined: 04/08/2023
Location: South Africa
Posts: 158
Posted: 02:04pm 26 Aug 2023
Copy link to clipboard 
Print this post

Thanks for the response and guidance phil99, matherp and TassyJim, much appreciated.

Peter’s explanation has resonated and I now realize that to achieve 2 decimal precision I would need a gate time of 100s, ie a count of 5001 in 100s will yield the desired 50.01Hz.

For my intended usage I will have to stick with period measurement to derive the frequency.

The GPS route sounds fascinating Jim. I wonder if an external RTC, DS3231’s 1Hz output would be stable enough as a reference. I assume your implementation did some sort of synchronization and then measured the phase drift.

Thanks again for your assistance.
Cheers Carl                                                        
Retirement is tough on Hobbies without a day job
 
Volhout
Guru

Joined: 05/03/2018
Location: Netherlands
Posts: 4246
Posted: 02:24pm 26 Aug 2023
Copy link to clipboard 
Print this post

The most accurate way to measure low frequencies (up to 20kHz) is measuring the period.
Using the picomite PIO allows for 44MHz tick (measurement resolution) at 133MHz CPUSPEED.
When measuring 50Hz you would get near 1ppm (1:1000000) resolution.

This is how it is done:

'PIO frequency counter for PICOMITE MMBasic measuring period time

'this is a PIO program
Dim a%(7)=(&h008400C5A029E020,&hE0408000A0CA0042,&h00C9008B004AA04A,&h8000A0C9,0,0,0,0)

'PIO configuration
f=133e6                     '133MHz PIO execution speed
e=Pio(execctrl gp0,0,31)    'use gp0 for PIN...select the input pin

'program pio1 and start
PIO program 1,a%()
PIO init machine 1,0,f,0,e
PIO start 1,0

'pio fifo register for reading information from PIO
Dim x%(4)

'read the PIO time counted and convert to frequency
Do
 PIO read 1,0,5,x%()           'read 5 count values, fifo + most recent  
 period = x%(4) + 4            'counts measured + instructions PIO setup time
 Print f/(3*period);" Hz"      'convert counts to Hz and print
 Pause 1000
Loop While Inkey$=""

end


In line 8 (e=Pio(execctrl gp0,0,31)) you can assign any gpio pin of the pico. e=Pio(execctrl gp26,0,31) uses gp26 (pin 31).

Success...

Volhout

P.S. if you use a picomiteVGA, you better set f=126e6 since it runs at 126MHz.
Edited 2023-08-27 00:33 by Volhout
PicomiteVGA PETSCII ROBOTS
 
carlschneider
Senior Member

Joined: 04/08/2023
Location: South Africa
Posts: 158
Posted: 03:03pm 26 Aug 2023
Copy link to clipboard 
Print this post

Hi Volhout

Thank you for the PIO solution.This is not something I have tried yet.

I have captured the PIO programming as you provided in the Pico running at 264MHz.


'Frequency pin test
If MM.Info(ip address) = "0.0.0.0" Then
Print "Failure to connect to the Internet - Restart"
CPU restart
EndIf
'
'
Print MM.Info(ip address)

On ERROR SKIP 5
WEB NTP -6 'Saskatoon
If MM.Errno Then WEB NTP -6
If MM.Errno Then WEB NTP -6
If MM.Errno Then Print "Failure to connect to the NTP Server" : CPU RESTART

Target=50.01
SetPin GP5, PWM2B
PWM 2, Target,, 50

'PIO frequency counter for PICOMITE MMBasic measuring period time

'this is a PIO program
Dim a%(7)=(&h008400C5A029E020,&hE0408000A0CA0042,&h00C9008B004AA04A,&h8000A0C9,
0,0,0,0)

'PIO configuration
f=264e6                     '264MHz PIO execution speed
e=Pio(execctrl gp6,0,31)    'use gp0 for PIN...select the input pin

'program pio1 and start
PIO program 1,a%()
PIO init machine 1,0,f,0,e
PIO start 1,0    

'pio fifo register for reading information from PIO
Dim x%(4)

'read the PIO time counted and convert to frequency
Do
PIO read 1,0,5,x%()           'read 5 count values, fifo + most recent
period = x%(4) + 4            'counts measured + instructions PIO setup time
Print f/(3*period);" Hz"      'convert counts to Hz and print
Pause 1000
Loop While Inkey$=""

End


Unfortunately there appears to be an error

> RUN
172.16.1.67
ntp address 209.115.181.107
got ntp response: 26/08/2023 08:55:40
[38] PIO program 1,a%()
Error : 1 is invalid (valid is 0 to 0)
> option list
WebMite MMBasic Version 5.07.07
OPTION COLOURCODE ON
OPTION CPUSPEED (KHz) 264000
OPTION DISPLAY 41, 140
OPTION WIFI Actiontec1177, **********
OPTION TCP SERVER PORT 80
OPTION TELNET CONSOLE ON

I checked in the manual and the example provides
PIO program 1, a%

So at this stage I'm fumbling around in the dark unfortunately.

Thank you for your assistance.
Cheers Carl                                                        
Retirement is tough on Hobbies without a day job
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 9126
Posted: 03:15pm 26 Aug 2023
Copy link to clipboard 
Print this post

The web version uses PIO 1 to interface the web chip so only PIO 0 is available
The VGA version uses PIO 0 to interface to the VGA display so only PIO 1 is available
The standard version has both PIO available

Just change all references to PIO 0 if running on the WebMite
 
carlschneider
Senior Member

Joined: 04/08/2023
Location: South Africa
Posts: 158
Posted: 03:23pm 26 Aug 2023
Copy link to clipboard 
Print this post

Thank you very much Volhout and Peter.

It works!

Much appreciated indeed.
Cheers Carl                                                        
Retirement is tough on Hobbies without a day job
 
Volhout
Guru

Joined: 05/03/2018
Location: Netherlands
Posts: 4246
Posted: 07:08pm 26 Aug 2023
Copy link to clipboard 
Print this post

Simplified and improved, and for PIO 0 on the webmite..

Note that the result accuracy is depending on the accuracy of the
crystal on the pico.

'PIO frequency counter for PICOMITE MMBasic

'PIO program
'this PIO program samples the GPx pin for edges in 2 loops
'that are 2 instructions per loop so the resulting count is in
'ticks that are 2/f seconds. Each GPx period is 2 instructions off.
Dim a%(7)=(&h0044004100c3a02b,&h8020a0c900c3,0,0,0,0,0,0)

'configure pio1
e=Pio(execctrl gp0,0,6)     'use gp0 for PIN
f=133e6                     '133MHz @ 2 instr per loop

'program pio0 and start
PIO program 0,a%()
PIO init machine 0,0,f,0,e
PIO start 0,0

'pio fifo register
Dim h%(4)

'read counted time, average over 4, and convert to frequency
Do
 PIO read 0,0,5,h%()
 period=(h%(1)+h%(2)+h%(3)+h%(4))/4 + 2    'skip h%(0) = rubbish
                                           'correct loop delay
 Print f/(2*period);" Hz"                  'convert to the Hz
 Pause 1000
Loop While Inkey$=""
PIO stop 0,0
End

Edited 2023-08-27 05:28 by Volhout
PicomiteVGA PETSCII ROBOTS
 
carlschneider
Senior Member

Joined: 04/08/2023
Location: South Africa
Posts: 158
Posted: 12:40am 27 Aug 2023
Copy link to clipboard 
Print this post

Hi Volhout

Some queries, if I may, to gain insight and expand my knowledge.

The WebMite manual v3 indicates that the MMBasic must assign the pin to the PIO with SetPin GPnn, PIO. I notice this has not been done in the example and does not appear to affect the operation of the program.

In the manual Read GPIO a,b,c,d indicates that c, the number of 32 bit words to read has a range 1..4 and I see you use 5 to include the latest reading.

In the normal usage of this method the very first 2 readings need to be discarded apparently. I assume this is due to the cleared FIFO register being filled as the PIO populates the FIFO with readings after the PIO start instruction.

My understanding is that there are 4 state machines per PIO and these operate independently; thus one could develop a further 3 state machines to do something else on PIO0?

Could you possibly provide the PIO menomics which yield the program contained in the array. I would like to understand what you did to get the period. I have tried to reverse engineer the a%() code but my depth of knowledge is lacking. The last time I did any menomic programming and state machines was in 1982 and rusty doesn't describe the holes in my memory on the subjects.  

I have run the PIO code on a PicoW and now need to migrate it to the Pico WH and see how it lives with the rest of the code :)

I really appreciate your assistance, thanks again.
Cheers Carl                                                        
Retirement is tough on Hobbies without a day job
 
phil99

Guru

Joined: 11/02/2018
Location: Australia
Posts: 2136
Posted: 01:22am 27 Aug 2023
Copy link to clipboard 
Print this post

Volhout's PIO introduction
 
carlschneider
Senior Member

Joined: 04/08/2023
Location: South Africa
Posts: 158
Posted: 02:09am 27 Aug 2023
Copy link to clipboard 
Print this post

Thanks for the revised PIO program, much appreciated.

I will follow the link provided and see to what level I can confuse myself.
Cheers Carl                                                        
Retirement is tough on Hobbies without a day job
 
Volhout
Guru

Joined: 05/03/2018
Location: Netherlands
Posts: 4246
Posted: 07:39am 27 Aug 2023
Copy link to clipboard 
Print this post

Hi Carl,

At time of writing, the picomite did not have a build in assembler for PIO.
It has now. And this is the same program when using the build in assembler. When assembling it immediately writes the program into memory.

'PIO frequency counter for PICOMITE MMBasic

'PIO program
'this PIO program samples the GPx pin for edges in 2 loops
'that are 2 instructions per loop so the resulting count is in
'ticks that are 2/f seconds. Each GPx period is 2 instructions off.
PIO assemble 0,".program period"
PIO assemble 0,".line 0"
pio assemble 0,".wrap target"
PIO assemble 0,"mov X,!null"
PIO assemble 0,"posloop:"
PIO assemble 0,"jmp pin negloop"
PIO assemble 0,"jmp x-- posloop"
PIO assemble 0,"negloop:"
PIO assemble 0,"jmp x-- next"
PIO assemble 0,"next:"
PIO assemble 0,"jmp pin negloop"
PIO assemble 0,"mov isr ,!x"
PIO assemble 0,"push noblock"
pio assemble 0,".wrap"
PIO assemble 0,".end program list"

'configure pio0
e=Pio(execctrl gp0,pio(.wrap target),pio(.wrap)) 'use gp0 for PIN
f=133e6                     '133MHz @ 2 instr per loop

'program pio0 and start
PIO init machine 0,0,f,0,e
PIO start 0,0

'pio fifo register
Dim h%(4)

'read counted time, average over 4, and convert to frequency
Do
 PIO read 0,0,5,h%()
 period=(h%(1)+h%(2)+h%(3)+h%(4))/4 + 2    'skip h%(0) = rubbish
                                           'correct loop delay
 Print f/(2*period);" Hz"                  'convert to the Hz
 Pause 1000
Loop While Inkey$=""
End


I hope this helps...

Volhout
Edited 2023-08-27 18:05 by Volhout
PicomiteVGA PETSCII ROBOTS
 
Volhout
Guru

Joined: 05/03/2018
Location: Netherlands
Posts: 4246
Posted: 08:26am 27 Aug 2023
Copy link to clipboard 
Print this post

@Carl,

You had another question I did not answer. About assigning a pin with SETPIN.

When you want PIO to control a pin, then you must inform MMBasic to reserve it for PIO. When you want PIO to only read the pin status (high or low) you do not need to do that. In fact, it can be used to your advantage.

The above program reads the pin status of GP0.
You can add 2 lines to the program so MMBasic uses the same GP0 pin for PWM

SETPIN gp0,PWM
PWM 0,5000,50


Now the PWM generates a 5000Hz test tone that PIO measures.

The reverse can also be done. Use SETPIN to assign a pin to PIO, make PIO generate a signal, and have MMBasic read the pin status with a=PIN(gpxx).

Both above cross-functions are used in the PicoMite VGA LA (logic analyzer) that uses the PIO to sample the analyzer signals, and MMBasic to control and display.
Edited 2023-08-27 18:29 by Volhout
PicomiteVGA PETSCII ROBOTS
 
carlschneider
Senior Member

Joined: 04/08/2023
Location: South Africa
Posts: 158
Posted: 03:30pm 27 Aug 2023
Copy link to clipboard 
Print this post

Thank you Volhout for your continued assistance.

I will continue to apply my mind to the information you have so kindly provided as well as the material you have published on TheBackShed per the link provided by phil99.

I note that the PIO Assembler writes directly to PIO memory. Using the assembler vs using the hand assembled string seems to take up more coding space. Not being able to read the 32 byte PIO memory makes the development cycle of PIO programs challenging :)

In your detailed explanation I now see how multiple state machine codes reside in the 32 byte PIO memory, thanks.

Your assistance is appreciated.
Cheers Carl                                                        
Retirement is tough on Hobbies without a day job
 
Chopperp

Guru

Joined: 03/01/2018
Location: Australia
Posts: 1057
Posted: 11:58pm 27 Aug 2023
Copy link to clipboard 
Print this post

Hi Carl & Volhout

Thanks for the posts. I was blatantly unaware of the PIO stuff.

I have the need to measure low frequency stuff as well & I've got the 2 PIO channels going measuring frequencies OK.

@Volhout. The only issue I have (so far) is that if the inputs drop off or become disconnected, the PIO still puts out readings, normally the same frequencies.

Is there a way of inhibiting the output (or something else) if there is no signal input? My immediate solution is to monitor the inputs with other input pins set to PIN (or FIN) to check that there is a signal there or not.

Again, thanks.

Brian
ChopperP
 
     Page 1 of 2    
Print this page
© JAQ Software 2024