![]() |
Forum Index : Microcontroller and PC projects : PicoMite Geiger Counter Interrupt Problem - Loop too short?!
Page 1 of 4 ![]() ![]() |
|||||
Author | Message | ||||
Amnesie Guru ![]() Joined: 30/06/2020 Location: GermanyPosts: 671 |
Hello again, this time I am working on a geiger counter (yes somehow triggered by the global 'events', but I have many gm-tubes flying around anyway). ![]() ![]() First: I am not in an age who is grown up with BASIC, so please keep in mind I am still lerning :) PROBLEM: The interrupt works perfectly fine with a small pause (~ >= 50ms) but does not with NO pause in the main "Do Loop". Without a pause, the "count" variable will not catch every interrupt. This is somehow counter intuitive for me, because I learned to keep everything short as possible and don't use any delay / pause since this is "bad practice". Is this behavior normal and I don't understand some fundamentals you could eventually point me at, or is it a bug? Why is a small pause in the "Do Loop" important for the interrupt service routine to count a variable up? Here is my full code with the remark in the Do Loop: 'IMPORTANT NOTE: 'Somehow it is relevant to provide the "Do Loop" at least 'with SOME pause (>=50ms) - otherwise the interrupts will 'not work correctly! Only some will trigger. ' SetPin gp0, intl, isr SetTick 60000, drawGraph Option explicit RTC gettime Dim integer min 'Array position of "minuteCount" Dim minutesCount(144) 'Array to store 576/4=144 minutes 'Declare Drawing variables ++++++++++++++++ Dim integer yRow, xCol, xDash, yDash, xScale, mScaleVal, yScale Dim integer xProgGraph=50, cGraph, cGraph_old, yGraphAdj=5 Dim float uScaleIndex, uScaleVal=0.096 'Declare Counting variables +++++++++++++++ Dim integer count, checkA CLS drawAxisGrit: min = 1 'Reset Array xProgGraph=50 'Reset Graph x-axis progress pixel to 50 CLS Box 0,2,637,20,1,RGB(green) 'Info Box Text 2,7,"GEIGER COUNTER V1.0 - BY D.SCHMAEH",,1,1,RGB(green) Box 0,23,637,40,1,RGB(green) 'Info Box 'Draw uSv/h & CPM ----------------------------- Text 1,30,"uSv/h: ",,5,1,RGB(green) Text 367,30,"CPM: ",,5,1,RGB(green) 'Draw dotted Grit ------------------------- For yRow=100 To 300 Step 20 'Draw Rows (300-100=200 -> 200/20 = 10 rows) For xCol=50 To 626 Step 24 'Draw Columns (626-50=576 -> 576/24 = 24 columns) Line xCol,yRow,xCol,yRow,,RGB(green) Next xCol Next yRow 'Draw solid Axis ------------------------- Line 50,300,626,300,,RGB(green) 'Draw X-axis Line 50,100,50,300,,RGB(green) 'Draw Y-axis 'Draw dashed lines ----------------------- For xDash=50 To 626 Step 24 'Draw dashed X Line xDash,297,xDash,305,,RGB(red) Next xDash For yDash=100 To 300 Step 20 'Draw dashed Y Line 45,yDash,53,yDash,,RGB(red) Next yDash 'Labels ------------------------------------------- Text 1,70,"uSv/h ",,1,1 'uSv/h Text 626,305,"t ",,1,1 'Time For xScale=40 To 626 Step 120 Text xScale,310,Str$(mScaleVal),,1,1 'Minutes Scale mScaleVal=mScaleVal+30 Next xScale mScaleVal=0 'Reset value for the next trigger For yScale=295 To 95 Step -20 Text 1,yScale,Str$(uScaleIndex),,1,1 'uSv/h Scale uScaleIndex=uScaleIndex+uScaleVal Next yScale uScaleIndex=0 'Reset value for the next trigger 'MAIN LOOP ################################################# Do If xProgGraph=626 Then GoTo drawAxisGrit 'If End of Scale redraw 'Draw Time & Date ----------------------------- Text 520,7,"TIME: "+Time$,,1,1,RGB(green) Text 370,7,"DATE: "+Date$,,1,1,RGB(green) Text 470,30,Str$(count),,5,1 Text 160,30,Str$(count * 0.0241),,5,1 Pause 100 'EXTREMLY IMPORTANT WITHOUT, THE LOOP IS SOMEHOW TO FAST TO REACT?! Loop '########################################################### 'Draw Graph ----------------------------------- drawGraph: xProgGraph = xProgGraph + 4 minutesCount(min)=count 'Store CPM to Array cGraph = count * yGraphAdj 'Graph enlargement Line xProgGraph-4,300-cGraph_old,xProgGraph,300-cGraph,,RGB(green) cGraph_old = cGraph count = 0 min = min+1 'Print Array Values to Check... For checkA=1 To 7 Text 1,350+checkA*15,Str$(minutesCount(checkA)),,1,1 Next checkA IReturn Sub isr 'Interrupt Service Routine triggered by Geiger Counter count = count + 1 End Sub Greetings Daniel Edited 2022-03-24 20:10 by Amnesie |
||||
thwill![]() Guru ![]() Joined: 16/09/2019 Location: United KingdomPosts: 4311 |
Hi, I'm not sure if it explains your problem, but SetTick fires an MMBasic software interrupt - you should do minimal processing within these, and your drawGraph() sub doesn't count as minimal processing. 1. Use SetTick to set a flag 'redraw% = 1' indicating it is time for a redraw. 2. Convert drawGraph() into a proper subroutine with SUB ... END SUB instead of using a labeled "GOSUB" ![]() 3. In your main loop add: If redraw% Then drawGraph() redraw% = 0 EndIf Hope this helps, Tom MMBasic for Linux, Game*Mite, CMM2 Welcome Tape, Creaky old text adventures |
||||
Plasmamac![]() Guru ![]() Joined: 31/01/2019 Location: GermanyPosts: 579 |
yap , as thwill wrote has nothing todo with your problem but ireturn is obsolete , use end sub or exit sub. whats your device ? where do you get 0.0241 ? neat idea , are the ebay things ok or must i build my own also ? gefaellt mir,gruss Plasma |
||||
Volhout Guru ![]() Joined: 05/03/2018 Location: NetherlandsPosts: 5089 |
Hi Amnesie, Your program is the "school-example" why the majority of software developers hate Basic. You use GOTO inside a loop to jump out of the loop and re-enter. drawAxisGrit: min = 1 .... ... ... 'MAIN LOOP ################################################# Do If xProgGraph=626 Then GoTo drawAxisGrit 'If End of Scale redraw .... .... .... Pause 100 'EXTREMLY IMPORTANT WITHOUT, THE LOOP IS SOMEHOW TO FAST TO REACT?! Loop I am abolutely not sure if this relates to your problem, but it is better to change the section of code that is in drawAxisGrit into a sub. sub drawAxisGrit ..... ..... end sub and then remove the "GOTO". to initialize, you simply remove the ":" (=colon) behind the label, since that will execute the sub. Edited 2022-03-24 21:45 by Volhout PicomiteVGA PETSCII ROBOTS |
||||
Amnesie Guru ![]() Joined: 30/06/2020 Location: GermanyPosts: 671 |
Thank you, I edited the code as suggested, but the problems persists. If I delete the "Pause 100" in the "Do Loop" there will nearly no new interrupt be recognized (only seldom). With the "Pause 100" in the Loop it works... I don't really understand this behavior... Here is the new Code with hopefully correct proper way of sub / end sub: ' 'IMPORTANT NOTE: 'Somehow it is relevant to provide the Do Loop at least 'with SOME pause (>=50ms) - otherwise the interrupts will 'not work correctly! ' ' SetPin gp0, intl, isr SetTick 60000, setRedrawFlag Option explicit RTC gettime Dim integer min 'Array position of "minuteCount" Dim minutesCount(144) 'Array to store 576/4=144 minutes 'Declare Drawing variables ++++++++++++++++ Dim integer yRow, xCol, xDash, yDash, xScale, mScaleVal, yScale Dim integer xProgGraph=50, cGraph, cGraph_old, yGraphAdj=5 Dim float uScaleIndex, uScaleVal=0.096 Dim integer redraw 'Declare Counting variables +++++++++++++++ Dim integer count, checkA CLS drawAxisGrid() Sub drawAxisGrid min = 1 'Reset Array xProgGraph=50 'Reset Graph x-axis progress pixel to 50 CLS Box 0,2,637,20,1,RGB(green) 'Info Box Text 2,7,"GEIGER COUNTER V1.0 - BY D.SCHMAEH",,1,1,RGB(green) Box 0,23,637,40,1,RGB(green) 'Info Box 'Draw uSv/h & CPM ----------------------------- Text 1,30,"uSv/h: ",,5,1,RGB(green) Text 367,30,"CPM: ",,5,1,RGB(green) 'Draw dotted Grit ------------------------- For yRow=100 To 300 Step 20 'Draw Rows (300-100=200 -> 200/20 = 10 rows) For xCol=50 To 626 Step 24 'Draw Columns (626-50=576 -> 576/24 = 24 columns) Line xCol,yRow,xCol,yRow,,RGB(green) Next xCol Next yRow 'Draw solid Axis ------------------------- Line 50,300,626,300,,RGB(green) 'Draw X-axis Line 50,100,50,300,,RGB(green) 'Draw Y-axis 'Draw dashed lines ----------------------- For xDash=50 To 626 Step 24 'Draw dashed X Line xDash,297,xDash,305,,RGB(red) Next xDash For yDash=100 To 300 Step 20 'Draw dashed Y Line 45,yDash,53,yDash,,RGB(red) Next yDash 'Labels ------------------------------------------- Text 1,70,"uSv/h ",,1,1 'uSv/h Text 626,305,"t ",,1,1 'Time For xScale=40 To 626 Step 120 Text xScale,310,Str$(mScaleVal),,1,1 'Minutes Scale mScaleVal=mScaleVal+30 Next xScale mScaleVal=0 'Reset value for the next trigger For yScale=295 To 95 Step -20 Text 1,yScale,Str$(uScaleIndex),,1,1 'uSv/h Scale uScaleIndex=uScaleIndex+uScaleVal Next yScale uScaleIndex=0 'Reset value for the next trigger End Sub 'MAIN LOOP ################################################# Do If xProgGraph=626 Then 'If End of Scale redraw drawAxisGrid() EndIf If redraw% Then 'every minute progress drawing the Graph drawGraph() redraw% = 0 EndIf 'Draw Time & Date ----------------------------- Text 520,7,"TIME: "+Time$,,1,1,RGB(green) Text 370,7,"DATE: "+Date$,,1,1,RGB(green) Text 470,30,Str$(count),,5,1 Text 160,30,Str$(count * 0.0241),,5,1 Pause 100 'EXTREMLY IMPORTANT WITHOUT, THE LOOP IS SOMEHOW TO FAST TO REACT?! Loop '########################################################### 'Draw Graph ----------------------------------- Sub drawGraph xProgGraph = xProgGraph + 4 minutesCount(min)=count 'Store CPM to Array cGraph = count * yGraphAdj 'Graph enlargement Line xProgGraph-4,300-cGraph_old,xProgGraph,300-cGraph,,RGB(green) cGraph_old = cGraph count = 0 min = min+1 'Print Array Values to Check... For checkA=1 To 7 Text 1,350+checkA*15,Str$(minutesCount(checkA)),,1,1 Next checkA End Sub Sub isr 'Interrupt Service Routine triggered by Geiger Counter count = count + 1 End Sub Sub setRedrawFlag redraw% = 1 End Sub Edited 2022-03-24 21:52 by Amnesie |
||||
Plasmamac![]() Guru ![]() Joined: 31/01/2019 Location: GermanyPosts: 579 |
whats your device? and MMB version Plasma |
||||
Amnesie Guru ![]() Joined: 30/06/2020 Location: GermanyPosts: 671 |
MMBasic Version 5.07.04b8 (VGA) as far as I know the latest... |
||||
Amnesie Guru ![]() Joined: 30/06/2020 Location: GermanyPosts: 671 |
Danke! I get the 0.0241 (conversion factor) by testing it with our official local radiation counter in our city and I do have some weak radioactive probes. Sadly I have no datasheet for this kind of tube... you can get gegier counters on eBay, but the shipping is slow from China and it is way overpriced so I built my own version of it, which works perfect. You can get the parts and tube in germany for really cheap! |
||||
pd-- Senior Member ![]() Joined: 11/12/2020 Location: AustraliaPosts: 122 |
There is no real time operating system , task scheduler , threading etc etc your do loop will consume all available cpu cycles and run as fast as it can unless you slow it down. A loop once a second would be fast enough ? or am i missing sumthing with my quick look at your code. |
||||
thwill![]() Guru ![]() Joined: 16/09/2019 Location: United KingdomPosts: 4311 |
That's not how MMBasic works (famous last words), it should be checking for MMBasic software interrupts between each BASIC command (MMBasic interrupts are not real "interrupts"), and infact I think a PAUSE is a "busy" PAUSE, i.e. it just spins the microcontroller - Peter would have to clarify. Best wishes, Tom MMBasic for Linux, Game*Mite, CMM2 Welcome Tape, Creaky old text adventures |
||||
Pluto Guru ![]() Joined: 09/06/2017 Location: FinlandPosts: 375 |
I have a similar kind of Geiger-meter (RadiationD v1.1 CAJOE from AliExpress) connected to PicoMiteVGA. My initial problem was to have Pico to recognize the pulses. The pulse out from Geiger is a short dip to "0V" and 5V between the pulses. I tried with serial resistor on the input to Pico; many pulses were missed. The final solution was to put a 47k potentiometer across the Geiger output and connect the wiper to PicoMite's input and adjust the idle voltage to about 3V. That seems to allow Pico to catch all pulses. I am counting pulses over a 10 minute period before plotting and saving to SD-card. Normal level is about 200 pulses/10minutes. ![]() Only recording nbr of pulses; No calibration to real radiation level. Tested by keeping a Americum radiation source from a smokealarm close to the tube and there was an enormous increase in pulse rate. I hope to never see that under normal (abnormal) measurement conditions! /Fred |
||||
Amnesie Guru ![]() Joined: 30/06/2020 Location: GermanyPosts: 671 |
Yes a loop through the (main Loop) once a second is enough in my case, but I was very curious, why it only works with a pause in the main loop since an interrupt does "its own thing", I thought... I just hoped someone could explain if I am doing something wrong because a pause seems not the right thing to do - but I am new to BASIC... |
||||
Amnesie Guru ![]() Joined: 30/06/2020 Location: GermanyPosts: 671 |
WOW This is so cool to see someone else is also interested in this and built something upon this. I dealt with the same "problems" with the 0 .. 5V pulses, I came up with exactly the same solution, just a voltage divider and it works... BUT ONLY WITH THE PAUSE in the Loop, I am wondering all the time... Since geiger counter (even the china ones) are really expensive I built my own version for about 20Euro and ordered some PCBs... |
||||
thwill![]() Guru ![]() Joined: 16/09/2019 Location: United KingdomPosts: 4311 |
I really don't think it should need the PAUSE, what does this pared down version do: SetPin gp0, intl, isr Dim count% Timer = 0 Do : Loop Sub isr() Inc count% Print Timer, count% End Sub Best wishes, Tom Edited 2022-03-24 22:35 by thwill MMBasic for Linux, Game*Mite, CMM2 Welcome Tape, Creaky old text adventures |
||||
Amnesie Guru ![]() Joined: 30/06/2020 Location: GermanyPosts: 671 |
Tested it! Works perfectly fine, it catches every count. But I am not really sure what this means... Why does this work without a pause? ... Aaah things getting strange... |
||||
thwill![]() Guru ![]() Joined: 16/09/2019 Location: United KingdomPosts: 4311 |
Also note that in your original code you setup the ISR before you've DIM'd the 'count' variable, so in theory it can fire before that variable is setup ... not sure what MMBasic is doing in that case when you declare it later ... perhaps the fact that it isn't reporting an error means the ISR isn't firing that early. Additionally my advice is that the first three lines of any MMBasic program should be: Option Base 0 Option Default None Option Explicit There will be some "Nay" sayers, but in the end this will save you a lot of heartache. Best wishes, Tom MMBasic for Linux, Game*Mite, CMM2 Welcome Tape, Creaky old text adventures |
||||
thwill![]() Guru ![]() Joined: 16/09/2019 Location: United KingdomPosts: 4311 |
Add the functionality of your old code a bit at a time until you find out when it stops working - it may not be you, it may be a firmware bug, the PicoMite is still pretty green. Best wishes, Tom Edited 2022-03-24 22:50 by thwill MMBasic for Linux, Game*Mite, CMM2 Welcome Tape, Creaky old text adventures |
||||
Pluto Guru ![]() Joined: 09/06/2017 Location: FinlandPosts: 375 |
This is my Geiger-code: 'MMEDIT!!! Basic Version = Pi_5.05.01 'MMEDIT!!! Port = COM28:38400:10,300 'MMEDIT!!! Device = Pi_5.05.01 'PicoMiteVGA. Displays Geiger-counter data on VGA-display. 'Counts the Geiger-pulses over 10minutes and displays data. 'Stores data on SD-card for each 10 minute period. 'RadiationD v1.1(CAJOE). Output from Geiger via headphone jack. '47k potentiometer used as voltage divider for input to PicomiteVGA. 'GP6 is used for pulse counting. 'RTC module for time. DS3231M module (note: diode not removed.) 'Fred 15.3.2022. 'setpin GP0,GP1,I2C RTC GETTIME cls TEXT mm.hres/2-30,10,"GEIGER FN2022 ","CM",1,1,rgb(cyan) dim Colors(9)=(RGB(yellow),RGB(RED),RGB(magenta),RGB(cyan),RGB(green),0,0,0,0,0) i=1 j=0 'For changing graph color when x-axis goes back from 320 to 0. Period=10*60*1000 'measurements collected over 10 minutes. 'Period=60*1000 'For debugging Ygrid OldPulCnt=0 'GUI LED #1,Puls,mm.hres*7/8,50,10,RGB(red) Circle mm.hres*7/8-15,40,10,1,1,RGB(red),rgb(bLACK) load JPG "Radiation2.jpg",mm.hres*7/8-22,32 'Circle mm.hres*7/8-15,40,5,1,4,RGB(red),-1 'Circle mm.hres*7/8-15,40,20,1,0.35,RGB(red),-1 'open "Geiger2.txt" for append as #1 DataFileName 'Create a name for the file where data is stored do timer=0 setpin GP6, CIN 'GP6 is one of the default counting pins. do text 10,50,time$,"LM",1,1,RGB(green) ProgressBar 'Shows the progress of the 10 minutes measurement period. NewPulCnt=pin(GP6) IF NewPulCnt>OldPulCnt then OldPulCnt=NewPulCnt Circle mm.hres*7/8-15,40,10,1,1,RGB(red),rgb(RED) 'indicator for rcvd pulse. text mm.hres*7/8,40,STR$(NewPulCnt)+" ","LM",1,1,RGB(white) Pause 100 'Just to keep the indicator briefly on. Circle mm.hres*7/8-15,40,10,1,1,RGB(BLACK),rgb(BLACK) load JPG "Radiation2.jpg",mm.hres*7/8-22,32 end if 'pause 500 loop until Timer>=Period OldPulCnt=-1 timer=0 Pulser=PIN(GP6) BOX i,(mm.vres-Pulser/5),2,2,1,Colors(j),Colors(j) TEXT 10,30,str$(Pulser)+" Pulser/10 minuter ","LM",1,1,rgb(Yellow) open NewFileName$ for append as #1 print #1, Date$+","+Time$+","+STR$(Pulser) Close #1 FS$=str$(mm.info$(filesize NewFileName$)) 'Size of present data-file. Text 190,20,"FS:"+FS$+" bytes ","LM",7,1,rgb(white) i=i+1 if i>320 then i=1:j=j+1 IF j>=4 then j=0 pin(GP6)=0 loop 'close #1 end sub DataFileName NewFileName$=Date$+" Geiger.txt" Text 190,10,NewFileName$,"LM",7,1,rgb(white) end sub sub ProgressBar IF Timer<1000 then BOX 0,60,mm.hres,5,1,RGB(cyan),RGB(black) box 0,60,mm.hres*timer/Period,5,1,RGB(cyan),rgb(Cyan) end sub SUB Ygrid xres=mm.hres yres=mm.vres 'line 0,yres,xres,yres,1,rgb(gray) 'line 0,yres/8,xres,yres/8,1,rgb(gray) 'line 0,yres*2/8,xres,yres*2/8,1,rgb(gray) line 0,yres*3/8,xres,yres*3/8,1,rgb(BLUE) line 0,yres*4/8,xres,yres*4/8,1,rgb(BLUE) line 0,yres*5/8,xres,yres*5/8,1,rgb(BLUE) Line 0,yres*6/8,xres,yres*6/8,1,rgb(BLUE) line 0,yres*7/8,xres,yres*7/8,1,rgb(BLUE) PAUSE 10 'pause for making the whole gr 'text xres-60,yres/8,"3.5","LM",3,1,rgb(Yellow) 'text xres-60,yres*2/8,"3.0","LM",3,1,rgb(Yellow) text xres-0,yres*3/8,"750","RM",7,1,rgb(BLUE) text xres-0,yres*4/8,"600","RM",7,1,rgb(BLUE) text xres-0,yres*5/8,"450","RM",7,1,rgb(BLUE) text xres-0,yres*6/8,"300","RM",7,1,rgb(BLUE) text xres-0,yres*7/8,"150","RM",7,1,rgb(BLUE) text xres-0,yres*8/8,"0","RM",7,1,rgb(BLUE) 'text xres-0,0,"4.0","LM",1,2,rgb(Yellow) 'for k=0 to xres step 200 'for m=0 to yres step yres/40 'text k,m,"+","CM",1,1,rgb(gray) 'next m 'next k end sub When the graph has reached the right end of the screen, it will jump back to start and plot the next set of data with an other color. In that way there can be a quite long datatrend visible and it is easy to see if there is something else than background scattering. Just above the graph is a 10minute long progress bar. Just to see when following datapoint is to be expected. I bought the Geiger-board several years ago and it has kindly rested in a box on the shelf until recently. Yellow dots and blue grid came just by "accident", but I recognize now that these are also the Ukrainian colors! /Fred |
||||
Amnesie Guru ![]() Joined: 30/06/2020 Location: GermanyPosts: 671 |
Done that, too. It solves not the problem, but is a good hint for me as a newbe. I am now stripping down the code piece by piece as you suggested. |
||||
Volhout Guru ![]() Joined: 05/03/2018 Location: NetherlandsPosts: 5089 |
Hi Amnesie, 1/ Can you use a variable named "min" used for minutes ? MIN is a basic keyword. 2/ when you declare the variable "redraw" as an integer, you do not need the trailing % (as in "redraw%"). Only when you no declare the variable you must use the % when it is supposed to be an integer. 3/ You use 2 interrupt routines, one for counting pulses, one for redrawing (1x per minute). Maybe this is causing problems. What is the behaviour you see ??? occasionally missing a pulse ? skipping halve the pulses ? only few pulses are measured ? Or does it see all pulses and the variable "count" is corrupted ? PicomiteVGA PETSCII ROBOTS |
||||
Page 1 of 4 ![]() ![]() |
![]() |
![]() |
The Back Shed's forum code is written, and hosted, in Australia. | © JAQ Software 2025 |