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 StatesPosts: 200 |
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: AustraliaPosts: 2136 |
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: NetherlandsPosts: 4247 |
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 KingdomPosts: 2129 |
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 KingdomPosts: 6798 |
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 KingdomPosts: 2129 |
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 KingdomPosts: 6798 |
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: AustraliaPosts: 2136 |
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 KingdomPosts: 2129 |
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 StatesPosts: 200 |
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 KingdomPosts: 2129 |
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 KingdomPosts: 9128 |
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 KingdomPosts: 2129 |
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 StatesPosts: 200 |
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: AustraliaPosts: 2136 |
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 StatesPosts: 200 |
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 StatesPosts: 200 |
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 KingdomPosts: 2129 |
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 KingdomPosts: 6798 |
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 KingdomPosts: 2129 |
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 |