Home
JAQForum Ver 24.01
Log In or Join  
Active Topics
Local Time 02:59 28 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 : Getting the best out of Pico ADC

     Page 4 of 17    
Author Message
NPHighview

Senior Member

Joined: 02/09/2020
Location: United States
Posts: 200
Posted: 12:03am 28 Jul 2023
Copy link to clipboard 
Print this post

I'm using PicoMite V5.07.08B8 from: https://geoffg.net/Downloads/picomite/PicoMite_Beta.zip
Live in the Future. It's Just Starting Now!
 
phil99

Guru

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

  Quote  Have you looked at the new ADC RUN command

Extracting the data from this involves using MEMORY UNPACK, and that is where I am stuck.
I can unpack the first element only. Can anyone show this thicko how to get the rest?

PicoMite MMBasic Version 5.07.08b9
Copyright 2011-2023 Geoff Graham
Copyright 2016-2023 Peter Mather

> dim integer a(3), b(31)

> a(0)=&Hfffefdfcfbfaefee
> a(1)=&Hedecebeadfdedddc
> a(2)=&Hdbdacfcecdcccbca
> a(3)=&Hbfbebdbcbbbaafae

> MEMORY UNPACK a(),b(),8,8

> for n=0 to 31:? hex$(b(n)),:next
EE      EF      FA      FB      FC      FD      FE      FF      0       0       0       0       0       0       0       0        0       0       0       0       0       0       0       0       0       0       0       0       0       0       0        0

> MEMORY UNPACK a(1),b(8),8,8

> for n=0 to 31:? hex$(b(n)),:next
EE      EF      FA      FB      FC      FD      FE      FF      0       0       0       0       0       0       0       0        0       0       0       0       0       0       0       0       0       0       0       0       0       0       0        0
>

Edit. Ignore the above.
The thicko thunked again. Result!
> MEMORY UNPACK a(),b(),32,8
> for n=0 to 31:? hex$(b(n)),:next                                                                                        
EE      EF      FA      FB      FC      FD      FE      FF      DC      DD      DE      DF      EA      EB      EC      ED       CA      CB      CC      CD      CE      CF      DA      DB      AE      AF      BA      BB      BC      BD      BE       BF
>

I used > MEMORY UNPACK a(),b(),8,8 as the manual seemed to indicate it would cut each 64-bit integer into eight 8-bit integers.
The first number is however the total number of slices for the whole array.
The order is reversed for each element of a() but that can be dealt with.

Another instance where a brief example would be worth a thousand words.

Edit 2
For the Scope program this is a more difficult way to get the same result.
Edited 2023-08-03 13:28 by phil99
 
Volhout
Guru

Joined: 05/03/2018
Location: Netherlands
Posts: 4247
Posted: 06:33am 03 Aug 2023
Copy link to clipboard 
Print this post

Hi Phil,

I used a ping-pong technique before (i.e. in a mains voltage analyzer).

ping-pong buffer and ADC

You can use that also for a scope, and the ADC START will also read 2 (or 3) ADC
channels in 12 bit resolution. But since the ping-pong handling is in MMBasic you will either
- have a 0.1ms blind gap (that is roughly how long it takes the interpreter between ping and pong).
- have to limit the sampling speed to 10kHz.

In my mains voltage analyzer I use 2 or 4 kHz sampling speed.

The ADC RUN command will do that much faster, so better suited for a scope. Unpacking is FAST. So the ADC RUN and MEMORY UNPACK is the best MMBasic combination for a scope.

Regards,

Volhout
Edited 2023-08-03 16:34 by Volhout
PicomiteVGA PETSCII ROBOTS
 
stanleyella

Guru

Joined: 25/06/2022
Location: United Kingdom
Posts: 2129
Posted: 06:05pm 03 Aug 2023
Copy link to clipboard 
Print this post

I still can't get triggering to work, with the "trigger" no display so it must stick there..-  do until (samples!(c%+1)>samples!(c%)):inc c%:loop 'trigger

 SetPin GP18,pwm1A 'this optional test signal comment out
 PWM 1,5000,50   ' 50% = square wave ,this optional test signal comment out
 
 dim c%,x%,samples!(200),old_samples!(200)
 SETPIN (31), AIn
 adc open 500000,1 'samples per second
 cls
 do
   adc start samples!() 'get new samples
   c%=0
   'do until (samples!(c%+1)>samples!(c%)):inc c%:loop 'trigger
   
   math scale samples!(),79,samples!()'scale to 80 pixel
   for x%=0 to 158 'screen width
     line x%,old_samples!(x%+c%),x%+1,old_samples!(x%+1+c%),,rgb(black) 'erase old_sample
     line x%,samples!(x%+c%),x%+1,samples!(x%+1+c%),,rgb(white) 'draw new sample
   next x%
   math add samples!(),0,old_samples!() 'copies new samples to old_samples
 loop
end
 
Mixtel90

Guru

Joined: 05/10/2019
Location: United Kingdom
Posts: 6798
Posted: 06:20pm 03 Aug 2023
Copy link to clipboard 
Print this post

Just an idea...

Very crude, but simply connect a DIN pin in parallel with the ADC pin. This will work because of the difference between Low and High logic signals. Wait for the DIN pin and a Trig Start button input to go high then ignore them and do one complete scan to fill the array(s) from the ADC. Make the array(s) big enough to give you several screen widths so that you can zoom and pan over the stored waveform. You now have a set of values that you can plot. Don't read any more samples until you manually restart the trigger.

Don't even attempt to synchronise the ADC collection with the waveform. You won't manage it.
Mick

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

Guru

Joined: 25/06/2022
Location: United Kingdom
Posts: 2129
Posted: 08:12pm 03 Aug 2023
Copy link to clipboard 
Print this post

  Mixtel90 said  Just an idea...

Very crude, but simply connect a DIN pin in parallel with the ADC pin. This will work because of the difference between Low and High logic signals. Wait for the DIN pin and a Trig Start button input to go high then ignore them and do one complete scan to fill the array(s) from the ADC. Make the array(s) big enough to give you several screen widths so that you can zoom and pan over the stored waveform. You now have a set of values that you can plot. Don't read any more samples until you manually restart the trigger.

Don't even attempt to synchronise the ADC collection with the waveform. You won't manage it.

it was recommended ie get the samples and check them for a rising edge but it stops the display. I can't see my error checking the samples for the next greater than current sample.
 
Mixtel90

Guru

Joined: 05/10/2019
Location: United Kingdom
Posts: 6798
Posted: 09:26pm 03 Aug 2023
Copy link to clipboard 
Print this post

You aren't interested in the display until the array is full. At that point you are no longer interested in collecting samples and can concentrate on the display. Don't try to display anything while you are collecting samples, it will slow things down.

Once you have that working you can start looking at other ideas like variable trigger points - which is best handled with a comparator to compare the input signal with a trig level pot. You might be able to use the ADC for that but a comparator is easy and can be expanded later for negative waveforms (when you will have to level shift the input signal because the Pico can only accept positive signals).
Mick

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

Guru

Joined: 11/02/2018
Location: Australia
Posts: 2136
Posted: 10:43pm 03 Aug 2023
Copy link to clipboard 
Print this post

Yes, that is the way to go. If you look back to my last scope program it does not look for the trigger until the array (at least double the elements of the screen width pixels) is full. It than scans through the array to find the trigger condition. Only then does it send the data to the display. Once the screen is full it repeats.
This method is reliable and stable. There are plenty of comments in it to help.

It should run as-is on your display. If the TEXT line is in the way use Font 8.

TEXT 0, 0, "T = "+Str$(HRes*1000/8/speed)+" mS/Div. V = 0.5V/Div.",,8
Edited 2023-08-04 09:22 by phil99
 
stanleyella

Guru

Joined: 25/06/2022
Location: United Kingdom
Posts: 2129
Posted: 07:46pm 04 Aug 2023
Copy link to clipboard 
Print this post

I tried another method using a buffer for graphics and the "trigger" works with pwm test signal.very stable.
 SetPin GP18,pwm1A 'this optional test signal comment out
 PWM 1,5000,50   ' 50% = square wave ,this optional test signal comment out
 dim c%,x%,samples!(360)
 SETPIN (31), AIn
 adc open 500000,1 'samples per second
 
FRAMEBUFFER CREATE F
FRAMEBUFFER WRITE F
do
adc start samples!() 'get new samples

'trigger
for c%=0 to 180
 If samples!(c%) > 0.1 then if samples!(c%+1)<0.2 then exit for
next c%

math scale samples!(),79,samples!()'scale to 80 pixel height
cls
   for x%=0 to 158 'screen width
     line x%,samples!(x%+c%),x%+1,samples!(x%+1+c%),,rgb(white) 'draw new sample
   next x%
FRAMEBUFFER COPY F,N
loop
Edited 2023-08-05 06:05 by stanleyella
 
NPHighview

Senior Member

Joined: 02/09/2020
Location: United States
Posts: 200
Posted: 11:16pm 04 Aug 2023
Copy link to clipboard 
Print this post

Very nice! I think the stability is due in some part to the divisibility of the square wave frequency into the AIN sampling frequency, though. With a PWM frequency of 7654 (not evenly divisible into 500000), you get some display jitter, but the triggering jitter is non-existent.

Also, brilliant use of pin 24 as a reference signal. I had just started wiring up a separate Pico for that, but hadn't yet got it going.

Here's a version that initializes the graticules, and then use array drawing commands for everything. The only thing I haven't figured out is how to use MATH commands to rapidly copy from the trigger point (at c%) to the display buffer without a FOR loop.

LOTS of setup (sorry!) in order to accomplish the Array graphics output.
' Sampling and Test Signal from Stanleyella
' Graticules and array drawing from NPHighview
' Test Signal output on GP18, PWM1A, or Pin 24
' Analog Signal input on GP26, or Pin 31

Const Hres  = MM.HRes
Const Vres  = MM.VRes
Const Voff  = .75*Vres

Const Background = RGB(32,64,32)
Const GMajor     = RGB(black)
Const GMinor     = RGB(black)
Const Signal     = RGB(yellow)

' Specifically For Waveshare RP2040-LCD-0.96

Const Major = Vres/4
Const Minor = Major/4

' Generic to all displays

Const HMajor = Hres/Major
Const VMajor = Vres/Major
Const HMinor = Hres/Minor
Const VMinor = Vres/Minor

'Const VScale = Vres/(-3.3)
Const VScale = Vres/(-5)

Dim Buffer!(Hres), Horizontal!(Hres)
Dim Integer x, y

Dim HMajorX1(HMajor+1), HMajory1(HMajor+1), HMajory2(HMajor+1) ' For Horizontal Major Axes
Dim VMajorX1(VMajor+1), VMajorx2(VMajor+1), VMajory1(VMajor+1) ' For Vertical   Major Axes

Dim HMinorX1(HMinor+1), HMinory1(HMinor+1), HMinory2(HMinor+1) ' For Horizontal Minor Axes
Dim VMinorX1(VMinor+1), VMinorx2(VMinor+1), VMinory1(VMinor+1) ' For Vertical   Minor Axes

Math Set 0, Buffer!()
Math Set 0, HMajory1() : Math Set Vres, HMajory2()  ' Set Arrays for Horiz Major Axis
Math Set 0, VMajorX1() : Math Set Hres, VMajorx2()  ' Set Arrays for Vert  Major Axis

Math Set Vres/2+Minor/2, HMinory1() : Math Set Vres/2-Minor/2, HMinory2() ' Set Arrays for Horiz Minor Axis
Math Set Hres/2+Minor/2, VMinorx1() : Math Set Hres/2-Minor/2, VMinorx2() ' Set Arrays for Vert  Minor Axis

For x = 0 To Hres-1 : horizontal!(x) = x    : Next x ' used in array graphics
For x = 0 To HMajor : HMajorx1(x) = x*Major : Next x ' for time  Major Axis graticule
For y = 0 To VMajor : VMajory1(y) = y*Major : Next y ' for Volts Major Axis graticule
For x = 0 To HMinor : HMinorx1(x) = x*Minor : Next x ' for time  Minor Axis graticule
For y = 0 To VMinor : VMinory1(y) = y*Minor : Next y ' for Volts Minor Axis graticule

SetPin GP18,pwm1A 'this optional test signal comment out
PWM 1,7654,50   ' 50% = square wave ,this optional test signal comment out
Dim c%,samples!(2*HRes)
SetPin (31), AIn
ADC open 500000,1 'samples per second

FRAMEBUFFER CREATE F
FRAMEBUFFER WRITE F

Do
 samples!(2*Hres-1) = -1
 ADC start samples!() 'get new samples
 Do While samples!(2*Hres-1) < 0 : Loop
 'trigger
 For c%=0 To HRes-1
   If samples!(c%) > 0.1 Then If samples!(c%+1)<0.2 Then Exit For
 Next c%
 For x%=0 To HRes-1 : buffer!(x%) = samples!(x%+c%) : Next x%

 Math Scale buffer!(), VScale, buffer!()                    ' Scale samples to fit vertically
 Math Add   buffer!(), Voff,   buffer!()                    ' Offset to bottom of screen (positive is up)
 CLS Background
 Line HMinorx1(), HMinory1(), HMinorx1(), HMinory2(), 1, GMinor ' Draw minor horiz graticules
 Line VMinorx1(), VMinory1(), VMinorx2(), VMinory1(), 1, GMinor ' Draw minor vert  graticules
 Line HMajorx1(), HMajory1(), HMajorx1(), HMajory2(), 1, GMajor ' Draw major horiz graticules
 Line VMajorx1(), VMajory1(), VMajorx2(), VMajory1(), 1, GMajor ' Draw major vert  graticules
 Pixel Horizontal(), buffer!(), Signal
Next x%

 FRAMEBUFFER COPY F,N
Loop




Live in the Future. It's Just Starting Now!
 
stanleyella

Guru

Joined: 25/06/2022
Location: United Kingdom
Posts: 2129
Posted: 04:21pm 05 Aug 2023
Copy link to clipboard 
Print this post

I think math scale only does the whole array ie samples() not from c% to c% + screen width and messing around defeats using math.

 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 9128
Posted: 05:05pm 05 Aug 2023
Copy link to clipboard 
Print this post

  Quote   The only thing I haven't figured out is how to use MATH commands to rapidly copy from the trigger point (at c%) to the display buffer without a FOR loop.


You can do this with memory copy

UNTESTED

a%=peek(varaddr samples!())
b%=peek(varaddr buffer!())
.....
memory copy FLOAT a%+c%*8,b%,HRes


Of course you can do the peeks outside the main loop
 
stanleyella

Guru

Joined: 25/06/2022
Location: United Kingdom
Posts: 2129
Posted: 05:09pm 05 Aug 2023
Copy link to clipboard 
Print this post

You can use the frame buffers to hold the cursor instead of redrawing it.

SetPin GP18,pwm1A 'this optional test signal comment out
PWM 1,10000,50  ' 50% square wave ,this optional test signal comment out
dim c%,x%,samples!(360)
SETPIN (31), AIn
adc open 500000,1 'samples per second
 
FRAMEBUFFER CREATE F
FRAMEBUFFER LAYER L
FRAMEBUFFER WRITE L
line 79,0,79,79,,rgb(red)
line 0,39,159,39,,rgb(red)
FRAMEBUFFER WRITE F

do
adc start samples!() 'get new samples

'trigger
c%=0
do:If samples!(c%) > 0.1 then if samples!(c%+1)<0.2 then exit do
inc c%:loop while c%<160

math scale samples!(),79,samples!()'scale to 80 pixel height
'cls



FRAMEBUFFER COPY L,F
for x%=0 to 158 'screen width
line x%,samples!(x%+c%),x%+1,samples!(x%+1+c%),,rgb(white) 'draw new sample
next x%
FRAMEBUFFER COPY F,N
loop

edit cls not needed
12345 Hz

Edited 2023-08-06 05:07 by stanleyella
 
NPHighview

Senior Member

Joined: 02/09/2020
Location: United States
Posts: 200
Posted: 11:40pm 08 Aug 2023
Copy link to clipboard 
Print this post

Thanks, Peter and Stanley! Framebuffer technique worked beautifully. But...

To test out a hypothesis, I had my main loop randomly adjust the duty cycle (between 10% and 30%) of a fixed frequency PWM on pin 24. This introduced a jitter in the displayed waveform (didn't affect triggering, only the jittery dance of the rising and falling display).

With the same trigger detection, I tried the Memory copy command, and got a screen with graticules & background, but no curve. Reverted to my one-line For loop, and got the jittery curve back.  In the listing below, Peter's technique is commented out, and the one-line For loop is active.

Is this attributable to the firmware version? Don't know, but here is my setup:
PicoMite MMBasic Version 5.07.08b8
OPTION SYSTEM SPI GP10,GP11,GP28
OPTION AUTORUN 2
OPTION COLOURCODE ON
OPTION HEARTBEAT OFF
OPTION CPUSPEED (KHz) 250000
OPTION DISPLAY 50, 132
OPTION LCDPANEL ST7735S, LANDSCAPE,GP8,GP12,GP9,GP25
OPTION AUDIO GP0,GP1, ON PWM CHANNEL 0


Here are snippets of my code:

...
Dim B_addr%, S_addr%                  ' Memory addresses of Buffer and Signal arrays
...
 B_Addr% = Peek(varaddr samples!())  ' from matherp's example on The Backshed Forum
 S_Addr% = Peek(varaddr Buffer!())   ' https://www.thebackshed.com/forum/ViewTopic.php?TID=16081&P=4
...
...
Sub Get_Samples   ' Obtains ADC samples into samples!(), then Buffer!() arrays
 samples!(2*Hres-1) = -1                                        ' Samples never < 0
 ADC start samples!() : Do While samples!(2*Hres-1) < 0 : Loop  ' wait for ADC completion

 For c%=0 To HRes-1                                             ' Find trigger point
   If samples!(c%) > 0.1 Then If samples!(c%+1)<0.2 Then Exit For
 Next c%

'  Memory copy FLOAT S_Addr%+c%*8, B_Addr%, Hres                ' Doesn't Work!
 For x%=0 To HRes-1 : buffer!(x%) = samples!(x%+c%) : Next x%  ' Offset-Copy into Display Buffer
End Sub


Here's the entire listing:

' Sampling, Test Signal, Framebuffers from stanleyella
' Math & Memory Copy from matherp
' Graticules and array drawing from NPHighview
' Test Signal output on GP18, PWM1A, or Pin 24
' Analog Signal input on GP26, or Pin 31
' Scale labels not calculated for the moment

Option EXPLICIT

Const Hres       = MM.HRes    ' Horizontal screen resolution
Const Vres       = MM.VRes    ' Vertical   screen resolution
Const VScale     = Vres/(-6.6)  ' Scale factor for display buffer
Const Voff       = .75*Vres   ' Offset for display buffer

' Specifically For Waveshare RP2040-LCD-0.96

Const Major      = Vres/4     ' Major tic mark spacing
Const Minor      = Major/4    ' Minor tic mark spacing

' Generic to all displays

Const HMajor     = Hres/Major ' How many Horiz Major Tic marks
Const VMajor     = Vres/Major ' How many Vert  Major Tic marks
Const HMinor     = Hres/Minor ' How many Horiz Minor Tic marks
Const VMinor     = Vres/Minor ' How many Vert  Minor Tic marks


Const Background = RGB(32,64,32) ' Color for Display background, a la Tektronix scopes
Const GMajor     = RGB(black)    ' Color for Major tic marks
Const GMinor     = RGB(black)    ' Color for Minor tic marks
Const Signal     = RGB(yellow)   ' Color for displayed signal
Const TxtColor   = RGB(cyan)     ' Color for displayed text

Const PWM_Freq   =   5000        ' Frequency for PWM test signal on Pin 24
Const ADC_Freq   = 400000        ' Sampling frequency for signal input on Pin 31
                                ' Note: >== Full waveform should be 100 pixels wide

Dim Horizontal!(Hres)            ' Horizontal coordinate buffer for fast graticule draw
Dim Buffer!(Hres)                ' Display buffer. As wide as LCD screen
Dim samples!(2*HRes)             ' Allow for twice the display width to capture a trigger
Dim c%                           ' Index of trigger condition in signal
Dim B_addr%, S_addr%             ' Memory addresses of Buffer and Signal arrays

Dim HMajorX1(HMajor+1), HMajory1(HMajor+1), HMajory2(HMajor+1) ' For Horizontal Major Axes
Dim VMajorX1(VMajor+1), VMajorx2(VMajor+1), VMajory1(VMajor+1) ' For Vertical   Major Axes

Dim HMinorX1(HMinor+1), HMinory1(HMinor+1), HMinory2(HMinor+1) ' For Horizontal Minor Axes
Dim VMinorX1(VMinor+1), VMinorx2(VMinor+1), VMinory1(VMinor+1) ' For Vertical   Minor Axes

Dim Integer x%, y%               ' Index values for drawing graticules

' Initialization Section - executed once

Initialize_Arrays
Initialize_Hardware

' Processing Section - looped forever

Do
 Randomize_Test_Signal
 Get_Samples
 Scale_Samples
 Update_Display
Loop

' Subroutines

Sub Draw_Graticules
 FRAMEBUFFER WRITE L                                            ' Write this once into Framebuffer L
 CLS Background                                                 ' Clear the screen to background color
 Line HMinorx1(), HMinory1(), HMinorx1(), HMinory2(), 1, GMinor ' Draw minor horiz graticules
 Line VMinorx1(), VMinory1(), VMinorx2(), VMinory1(), 1, GMinor ' Draw minor vert  graticules
 Line HMajorx1(), HMajory1(), HMajorx1(), HMajory2(), 1, GMajor ' Draw major horiz graticules
 Line VMajorx1(), VMajory1(), VMajorx2(), VMajory1(), 1, GMajor ' Draw major vert  graticules
 Text    0, Vres, "50 uSec", LB, 7, 1, TxtColor, Background     ' Draw Time Scale at LL
 Text Hres, Vres, "1.0 V",   RB, 7, 1, TxtColor, Background     ' Draw Volts Scale at LR
End Sub

Sub Randomize_Test_Signal
 PWM 1, PWM_Freq, 10+20*Rnd   ' Randomize duty cycle to ensure displayed signal is refreshing
End Sub

Sub Get_Samples   ' Obtains ADC samples into samples!() array
 samples!(2*Hres-1) = -1                                        ' Samples will never be < 0
 ADC start samples!() : Do While samples!(2*Hres-1) < 0 : Loop  ' wait for ADC completion

 For c%=0 To HRes-1                                             ' Find a trigger point
   If samples!(c%) > 0.1 Then If samples!(c%+1)<0.2 Then Exit For
 Next c%

'  Memory copy FLOAT S_Addr%+c%*8, B_Addr%, Hres  ' from matherp's example see URL above
 For x%=0 To HRes-1 : buffer!(x%) = samples!(x%+c%) : Next x%  ' Offset-Copy into Display Buffer
End Sub

Sub Scale_Samples
 Math Scale buffer!(), VScale, buffer!()                    ' Scale samples to fit vertically
 Math Add   buffer!(), Voff,   buffer!()                    ' Offset to bottom of screen (positive is up)
End Sub

Sub Update_Display
 FRAMEBUFFER COPY L, F ' Pick up screen background and graticules
 FRAMEBUFFER WRITE F : Pixel Horizontal(), buffer!(), Signal
 FRAMEBUFFER COPY F,N
End Sub

Sub Initialize_Arrays
 B_Addr% = Peek(varaddr samples!())  ' from matherp's example on The Backshed Forum
 S_Addr% = Peek(varaddr Buffer!())   ' https://www.thebackshed.com/forum/ViewTopic.php?TID=16081&P=4

' Print "Buffer Address:  "; Hex$(B_Addr%)
' Print "Samples Address: "; Hex$(S_Addr%)

 Math Set 0, Buffer!()                               ' Zero out the display buffer
 Math Set 0, HMajory1() : Math Set Vres, HMajory2()  ' Set Arrays for Time  Major Axis
 Math Set 0, VMajorX1() : Math Set Hres, VMajorx2()  ' Set Arrays for Volts Major Axis

 Math Set Vres/2+Minor/2, HMinory1() : Math Set Vres/2-Minor/2, HMinory2() ' Set Arrays for Time  Minor Axis
 Math Set Hres/2+Minor/2, VMinorx1() : Math Set Hres/2-Minor/2, VMinorx2() ' Set Arrays for Volts Minor Axis

 For x = 0 To Hres-1 : horizontal!(x) = x    : Next x ' used in array graphics
 For x = 0 To HMajor : HMajorx1(x) = x*Major : Next x ' for Time  Major Axis graticule
 For y = 0 To VMajor : VMajory1(y) = y*Major : Next y ' for Volts Major Axis graticule
 For x = 0 To HMinor : HMinorx1(x) = x*Minor : Next x ' for Time  Minor Axis graticule
 For y = 0 To VMinor : VMinory1(y) = y*Minor : Next y ' for Volts Minor Axis graticule

End Sub

Sub Initialize_Hardware
 SetPin GP18,pwm1A    ' Set up pin 24 for PWM test signal out
 PWM 1, PWM_Freq, 10  ' Square wave on Pin 24
 SetPin (31), AIn     ' ADC input on   Pin 31
 ADC open ADC_Freq, 1 ' Sample at specified samples per second

 FRAMEBUFFER CREATE F
 FRAMEBUFFER LAYER  L
 Draw_Graticules
End Sub


and here's its current appearance:

Live in the Future. It's Just Starting Now!
 
phil99

Guru

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

A test version of Peters method, with minor adjustment, does work.
Integers are used in this example as ADC RUN returns 8-bit integers representing 0 to 3.3V (the top 8 bits of the raw ADC data I think) but FLOAT also works.

> LIST
Dim integer a, b, c = 5, n, HRes = 10
Dim integer s.in(20), s.out(10)

a=Peek(varaddr s.in())
b=Peek(varaddr s.out())

For n = 0 To 19 'fill the input sample array
 s.in(n) = n
Next

Memory copy INTEGER a + c * 8, b, HRes

For n = 0 To 9   'read the output sample array
 Print s.out(n),
Next
>
> RUN
5       6       7       8       9       10      11      12      13      14
>

Edited 2023-08-09 11:09 by phil99
 
NPHighview

Senior Member

Joined: 02/09/2020
Location: United States
Posts: 200
Posted: 09:57pm 09 Aug 2023
Copy link to clipboard 
Print this post

OK - that makes sense. I've emulated your code (see below), but for floats (as ADC start sample returns floats from 0 to 3.3), and it works (probably no surprise). Now to figure out what I'm doing wrong in my much longer scope code (maybe depending on % and ! to control variable typing instead of explicitly stating).


Dim Integer c=5, n, HRes=MM.HRes

Dim Float   signal(HRes*2), buffer(Hres)
Dim Integer addr.signal, addr.buffer

addr.signal = Peek(varaddr signal()) : Print "*signal = "; addr.signal
addr.buffer = Peek(varaddr buffer()) : Print "*buffer = "; addr.buffer

For n = 0 To (Hres*2)-1
 signal(n) = n/100
Next

Memory copy FLOAT   addr.signal + c*8, addr.buffer, Hres

For n = 0 To Hres-1
 Print Str$(n, 3, 0), "Floats: ";Str$(signal(n+c),3,2); " -> "; Str$(buffer(n),3,2)
Next

Live in the Future. It's Just Starting Now!
 
NPHighview

Senior Member

Joined: 02/09/2020
Location: United States
Posts: 200
Posted: 01:02am 10 Aug 2023
Copy link to clipboard 
Print this post

Well, it's a mystery. Basically, retyping the whole thing back in (making some structure and declaration changes along the way) now results in the memory copy working. Wow - it's fast!

Thanks again to stanleyella and matherp for hints :-)

I've added what are essentially ENUMs in other languages to specify whether the trigger condition should be positive, negative, or free-running, and added that to the code. I've also begun calculating the actual horizontal resolution and displaying it, as a precursor to adding some UI to adjust.


' Sampling, Test Signal, Framebuffers from stanleyella
' Math & Memory Copy from matherp
' Triggers, Graticules and Array Drawing from NPHighview
' Test Signal output on GP18, PWM1A, or Pin 24
' Analog Signal input on GP26, or Pin 31
' Time Scale labels are calculated; volts scale not calculated for the moment

Option EXPLICIT

Const PWM_Freq   =   5000         ' Frequency for Test Signal on Pin 24
Const ADC_Freq   = 500000         ' Sampling frequency for sample input on Pin 31
                                 ' Note: >== Full waveform should be ~100 pixels wide

Const Hres       = MM.HRes        ' Horizontal screen resolution
Const Vres       = MM.VRes        ' Vertical   screen resolution

Const VScale     = Vres/(-5)      ' Scale factor for display buffer
Const Voff       = .75*Vres       ' Offset for display buffer

' Specifically For Waveshare RP2040-LCD-0.96

Const Major      = Vres/4         ' Major tic mark spacing
Const Minor      = Major/4        ' Minor tic mark spacing

' Generic to all displays

Const HMajor     = Hres/Major     ' How many Horiz Major Tic marks
Const VMajor     = Vres/Major     ' How many Vert  Major Tic marks
Const HMinor     = Hres/Minor     ' How many Horiz Minor Tic marks
Const VMinor     = Vres/Minor     ' How many Vert  Minor Tic marks

Const Background = RGB(32,64,32)  ' Color for Display background, a la Tektronix scopes
Const GMajor     = RGB(black)     ' Color for Major tic marks
Const GMinor     = RGB(black)     ' Color for Minor tic marks
Const Signal     = RGB(yellow)    ' Color for displayed signal
Const TxtColor   = RGB(cyan)      ' Color for displayed text

Const Trig_None  = 0
Const Trig_Down  = 1              ' Enumerate possible trigger conditions
Const Trig_Up    = 2


Dim INTEGER Horizontal(Hres)      ' Horizontal coordinate buffer for fast graticule and buffer draw

Dim INTEGER c, n, x, y, trigger

Dim FLOAT   sample(2*Hres)        ' Extra size to hopefully pick up a trigger event
Dim FLOAT   buffer(Hres)          ' Display buffer for screen output
Dim INTEGER addr.sample, addr.buffer

Dim INTEGER HMajorX1(HMajor+1), HMajory1(HMajor+1), HMajory2(HMajor+1) ' For Horizontal Major Axes
Dim INTEGER VMajorX1(VMajor+1), VMajorx2(VMajor+1), VMajory1(VMajor+1) ' For Vertical   Major Axes

Dim INTEGER HMinorX1(HMinor+1), HMinory1(HMinor+1), HMinory2(HMinor+1) ' For Horizontal Minor Axes
Dim INTEGER VMinorX1(VMinor+1), VMinorx2(VMinor+1), VMinory1(VMinor+1) ' For Vertical   Minor Axes

' ========================== Initialization =================================
Initialize_Arrays
Initialize_Hardware
Draw_Graticules

' ========================== Processing Loop ================================
Do
 Randomize_Test_Signal
 Do
   trigger = -1
   Get_Samples
   trigger = find_trigger(Trig_Down)
 Loop Until trigger >= 0
 Scale_Samples
 Update_Display
Loop

' ========================== Subs and Functions ============================

Function find_trigger(a)
 Select Case a
   Case Trig_Down
     For c = 0 To Hres-1
       If sample(c) > 0.1 And sample(c+1) < 0.2 Then find_trigger = c : Exit Function
     Next
     find_trigger = -1 : Exit Function
   Case Trig_Up
     For c = 0 To Hres-1
       If sample(c+1) > 0.1 And sample(c) < 0.2 Then find_trigger = c : Exit Function
     Next
     find_trigger = -1 : Exit Function
   Case Else
     find_trigger = 0 : Exit Function
 End Select
End Function

Function volt_tic(VSc As Float, Maj As Integer) As Float
 volt_tic = 1.0
End Function

Sub Initialize_Arrays
 addr.sample = Peek(varaddr sample())
 addr.buffer = Peek(varaddr buffer())

 Math Set 0, HMajory1() : Math Set Vres, HMajory2()  ' Set Arrays for Time  Major Axis
 Math Set 0, VMajorX1() : Math Set Hres, VMajorx2()  ' Set Arrays for Volts Major Axis

 Math Set 3*Vres/4+Minor/2, HMinory1()
 Math Set 3*Vres/4-Minor/2, HMinory2() ' Set Arrays for Time  Minor Axis
 Math Set Hres/2+Minor/2, VMinorx1()
 Math Set Hres/2-Minor/2, VMinorx2() ' Set Arrays for Volts Minor Axis

 For x = 0 To Hres-1 : Horizontal(x) = x     : Next ' used in array graphics
 For x = 0 To HMajor : HMajorx1(x) = x*Major : Next ' for Time  Major Axis graticule
 For y = 0 To VMajor : VMajory1(y) = y*Major : Next ' for Volts Major Axis graticule
 For x = 0 To HMinor : HMinorx1(x) = x*Minor : Next ' for Time  Minor Axis graticule
 For y = 0 To VMinor : VMinory1(y) = y*Minor : Next ' for Volts Minor Axis graticule

End Sub

Sub Initialize_Hardware
 SetPin GP18, PWM1A    ' Set up pin 24 for PWM test signal output
 PWM 1, PWM_Freq, 10   ' Low Duty Cycle square wave on Pin 24
 SetPin (31), AIn      ' ADC input on Pin 31
 ADC open ADC_Freq, 1  ' Sample at specified frequency

 FRAMEBUFFER CREATE F
 FRAMEBUFFER LAYER  L
End Sub

Sub Draw_Graticules
 Local STRING T$, V$
 FRAMEBUFFER WRITE L
 CLS Background
 Line HMinorx1(), HMinory1(), HMinorx1(), HMinory2(), 1, GMinor ' Draw minor horiz graticules
 Line VMinorx1(), VMinory1(), VMinorx2(), VMinory1(), 1, GMinor ' Draw minor vert  graticules
 Line HMajorx1(), HMajory1(), HMajorx1(), HMajory2(), 1, GMajor ' Draw major horiz graticules
 Line VMajorx1(), VMajory1(), VMajorx2(), VMajory1(), 1, GMajor ' Draw major vert  graticules

 T$ = Str$(1000000*Major/ADC_Freq,3,0) + " uSec"
 Text    0, Vres, T$, LB, 7, 1, TxtColor, Background     ' Draw Time Scale at LL
 V$ = Str$(1.0, 2, 1)+" V"
 Text Hres, Vres, V$, RB, 7, 1, TxtColor, Background     ' Draw Volts Scale at LR
End Sub

Sub Randomize_Test_Signal
 PWM 1, PWM_Freq, 45+10*Rnd  ' Randomize duty cycle to ensure displayed signal is refreshing
End Sub

Sub Get_Samples               ' Load ADC inputs into sample() array
 sample(2*Hres-1) = -1       ' Samples will never be < 0
 ADC start sample() : Do While sample(2*Hres-1) < 0 : Loop
End Sub

Sub Scale_Samples
 Memory copy FLOAT addr.sample + trigger*8, addr.buffer, Hres
 Math Scale buffer!(), VScale, buffer!()                    ' Scale samples to fit vertically
 Math Add   buffer!(), Voff,   buffer!()                    ' Offset to bottom of screen (positive is up)
End Sub


Sub Update_Display
 FRAMEBUFFER COPY L, F
 FRAMEBUFFER WRITE F : Pixel Horizontal(), buffer(), Signal
 FRAMEBUFFER COPY F,N
End Sub

Edited 2023-08-11 00:34 by NPHighview
Live in the Future. It's Just Starting Now!
 
stanleyella

Guru

Joined: 25/06/2022
Location: United Kingdom
Posts: 2129
Posted: 03:03pm 10 Aug 2023
Copy link to clipboard 
Print this post

  Mixtel90 said  Just an idea...

Very crude, but simply connect a DIN pin in parallel with the ADC pin. This will work because of the difference between Low and High logic signals. Wait for the DIN pin and a Trig Start button input to go high then ignore them and do one complete scan to fill the array(s) from the ADC. Make the array(s) big enough to give you several screen widths so that you can zoom and pan over the stored waveform. You now have a set of values that you can plot. Don't read any more samples until you manually restart the trigger.

Don't even attempt to synchronise the ADC collection with the waveform. You won't manage it.


do:if pin(32) =1 then exit do:loop' the trigger
adc start samples!() 'get new samples.
No joy.
do until pin(32)=1:loop' no joy
pin (32) is connected to the pwm test signal pin and adc in pin.

I haven't installed the beta version with adcrun yet to try.
 
Mixtel90

Guru

Joined: 05/10/2019
Location: United Kingdom
Posts: 6798
Posted: 03:18pm 10 Aug 2023
Copy link to clipboard 
Print this post

The point is that collecting the samples into an array and displaying them are two different tasks that are done alternately, never together. Once you have an array of values you just plot them, with scale, zoom, pan or whatever. The waveform will *always* be rock solid as the ADC isn't running. You can, for example, refill the array every second then go back to plotting it. You don't *have* to synchronise anything.
Mick

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

Guru

Joined: 25/06/2022
Location: United Kingdom
Posts: 2129
Posted: 04:38pm 10 Aug 2023
Copy link to clipboard 
Print this post

Ta Mick. It's not a "real" scope but could be useful.. my code is short and shows pwm signal or sound ..after filter.
Assuming it's a repetitive wave then oversampling more than the display width and finding a trigger sort of works ok but my trigger is too simple to be true.

 SetPin GP18,pwm1A 'this optional test signal comment out
 PWM 1,9876,30  'square wave ,this optional test signal comment out
 dim c%,x%,samples!(320)
 SETPIN (31), AIn
 adc open 500000,1 'samples per second
 
 FRAMEBUFFER CREATE F
 FRAMEBUFFER LAYER L
 FRAMEBUFFER WRITE L
 line 79,0,79,79,,rgb(green)
 line 0,39,159,39,,rgb(green)
 FRAMEBUFFER WRITE F
 
 do
   adc start samples!() 'get new samples
   'trigger
   c%=0
  do:If samples!(c%) > 0.1 then if samples!(c%+1) < 0.2 then exit do
inc c%:loop while c%<160

math scale samples!(),79,samples!()'scale to 80 pixel height
FRAMEBUFFER COPY L,F
for x%=0 to 158 'screen width
     line x%,samples!(x%+c%),x%+1,samples!(x%+1+c%),,rgb(magenta) 'draw new sample from sample(c%)
next x%
FRAMEBUFFER COPY F,N
 loop

 
     Page 4 of 17    
Print this page
© JAQ Software 2024