![]() |
Forum Index : Microcontroller and PC projects : Micromite V5.04.09 Beta 19
![]() ![]() ![]() ![]() |
|||||
Author | Message | ||||
Frank N. Furter Guru ![]() Joined: 28/05/2012 Location: GermanyPosts: 949 |
SOMETHING'S WRONG WITH PWM AND INTERRUPT ON V19! I used a modified version of this code (Decoding DIGOO remote temperature sensor) for reading my old rain sensor WS7058 (many thanks to disco4now and tassiejim!!!). Until now I used the V5.04.09 Beta 3 version which worked without problems. The WS7058 rain sensor has shorter bits and another start- and stop behaviour as DIGOO and sends 44 bytes. Amazingly, the DIGOO sensor still works under Beta 19 - but all I get back from my rain sensor is garbage! I have flashed the PIC several times with Beta 19 and Beta 3 - always with the same result - Beta 3 works perfect, Beta 19 does not work (with the same code)! I always get less bytes than expected and they are usually wrong! Here is my code: ' Credits: Tassie Jim for initial decoding code and Gerry Allardice Dim ProgTitle$ = "Lacrosse RAIN DECODER" ' Dim ProgVer$ = "v1.0.0" ' Dim ProgDate$ = "11-Mai-2018" ' '------------------------------------------------------------------------------' ' The Lacrosse RAIN sensor sends code to the console station via 433.92MHz ASK code. ' It can be decoded by using a 433.92 reciever connected to a digital pin eg(16). '*** Option Explicit Option Default NONE '==================================================================================== ' Data Variables '==================================================================================== Dim tick As INTEGER, tock As INTEGER Dim code$,codeinv$ Dim D01 As INTEGER Dim D02 As INTEGER Dim D03 As INTEGER '==================================================================================== ' Program Initialization '==================================================================================== Print "Starting " + ProgTitle$ + ": " + ProgVer$ + " - " + ProgDate$ PWM 1, 100000, 50 '100000' this is out high resolution timer which gets connected 'to pin 15 SetPin 15, CIN SetPin 16, INTL, blip ' triggers on a high to low transition '==================================================================================== ' Main program loop '==================================================================================== Do 'IF INKEY$<>"" THEN 'PRINT code$ 'ENDIF Loop End Sub blip tock=tick tick = Pin(15) Select Case tick-tock Case > 3000 If Len(code$)=43 Then Print Mid$( code$, 1, 3); Print" "; Print Mid$( code$, 4, 4); Print" "; Print Mid$( code$, 8, 4); Print" "; Print Mid$( code$, 12, 4); Print" "; Print Mid$( code$, 16, 4); Print" < "; Print Mid$( code$, 20, 4); Print" "; Print Mid$( code$, 24, 4); Print" "; Print Mid$( code$, 28, 4); Print" "; Print Mid$( code$, 32, 4); Print" "; Print Mid$( code$, 36, 4); Print" > "; Print Mid$( code$, 40, 4); Print" - "; D03 = Val("&b"+Mid$( code$, 20, 12)) Print D03 EndIf code$="" codeinv$="" Case > 2800 code$="" codeinv$="" Case > 220 code$ = code$ + "0" codeinv$= codeinv$+"1" Case > 110 code$ = code$ + "1" codeinv$= codeinv$+"0" Case Else code$="" codeinv$="" End Select If Len(code$)>44 Then code$="" codeinv$="" Frank |
||||
Geoffg![]() Guru ![]() Joined: 06/06/2011 Location: AustraliaPosts: 3292 |
I'm a bit confused here. The example on page 36 works as it should, there is no need to declare the variables as integers (they default to floats). The only part of the example that is wrong is the error message which, in later versions, now would be Error: Function or array NR not declared. Just to be clear, below is a listing of the code and the error message. > LIST Option EXPLICIT Dim Nbr, Incr, Total Nbr = 1234 Incr = 2 Total = Nr + Incr > RUN [5] Total = Nr + Incr Error: Function or array NR not declared > EDIT: I just noticed that the error message should read Error: Function or variable NR not declared. That is something I will investigate but, regardless, you do not need integer variables. Geoff Geoff Graham - http://geoffg.net |
||||
Geoffg![]() Guru ![]() Joined: 06/06/2011 Location: AustraliaPosts: 3292 |
Thanks, well spotted. I will fix it in the next beta. Geoff Geoff Graham - http://geoffg.net |
||||
Geoffg![]() Guru ![]() Joined: 06/06/2011 Location: AustraliaPosts: 3292 |
Hmm, nothing has changed with both the PWM and interrupt functionality. I will check through the source in detail but I cannot see what could be the issue. I think that you are going to have to investigate further, one possibility could be that the interrupts are coming too fast and some small change between versions has marginally slowed down the code in your interrupt sub. For example, your interrupt sub has a lot of code in it including PRINT statements - that is not good, interrupts should always be very short. With all that code in there it is quite possible that the interrupts are coming too fast for the program to work reliably BTW, I could not find the END SUB for your interrupt sub. Geoff Geoff Graham - http://geoffg.net |
||||
Grogster![]() Admin Group ![]() Joined: 31/12/2012 Location: New ZealandPosts: 9610 |
From the MicroMite bible: "Thou shalt not hang around in interrupts." ![]() What I have taken to doing in interrupts, is just set a flag and exit. That keeps the interrupt very short, and the main loop can just check the flag to see if it needs to do anything. I did learn this the hard way, after making interrupts run the code I wanted to have happen on the interrupt. That is the way your brain wants to do it, but you have to rethink when it comes to interrupts. ![]() ![]() Smoke makes things work. When the smoke gets out, it stops! |
||||
GoodToGo!![]() Senior Member ![]() Joined: 23/04/2017 Location: AustraliaPosts: 188 |
So Grogs, once your main loop has checked for a flag set by an interrupt sub, do you branch it off to another sub where the code is or do you just put it all the code in the main loop? ![]() Cheers, GTG! ![]() ...... Don't worry mate, it'll be GoodToGo! |
||||
CaptainBoing![]() Guru ![]() Joined: 07/09/2016 Location: United KingdomPosts: 2170 |
That is one of the great debates and depends on your own programming style ![]() Personally, if a piece of code is only going to be used once, I really don't like having it as a SUB or FUNCTION. It can improve readability of the program though, especially if the relevant bit of code is long. do what works for you. |
||||
Grogster![]() Admin Group ![]() Joined: 31/12/2012 Location: New ZealandPosts: 9610 |
I have an IF/THEN(ELSE) as part of the main loop, and if the flag is set, the IF/THEN(ELSE) picks up on that, and executes that code. You can have multiple IF/THEN(ELSE) routines inside the main loop, to pick up and act on any of the flags set in any of the interrupts. If the code is really big, then the IF/THEN(ELSE) can call a sub to deal with it, but mainly I just have all I need inside the IF/THEN(ELSE). Or, I have several small subs that you can call one after the other inside the IF/THEN(ELSE) if you need to keep it neat. Smoke makes things work. When the smoke gets out, it stops! |
||||
MicroBlocks![]() Guru ![]() Joined: 12/05/2012 Location: ThailandPosts: 2209 |
If something is time consuming you can break it up in several 'states'. You set a counter to 0 on the beginning and execute some code, then increase the counter. In a loop you check the counter and this will determine which 'state' has to be processed. Each time a step has been done you increase the counter or even set the counter to a specific value to repeat or skip steps. Especially good if there are large loops and cpu intensive code as you can then easily divide it into smaller blocks. The other parts of the program then also get time to process. It is a way to simulate multi tasking and if it is done quick enough the user will experience it like that. Microblocks. Build with logic. |
||||
Frank N. Furter Guru ![]() Joined: 28/05/2012 Location: GermanyPosts: 949 |
@Geoff: ...you are right, there was a copy/paste error in my code. My original code has these two lines at the end: EndIf End Sub Now I can say "MMBasic Ver 5.04.09 Beta 16" works also without problems!!! I can see nothing unusual with my logic analyzer or oscilloscope on the 100Khz PWM and Beta 19... Did you have another version of MMBASIC which I could try? ...or did you have another idea? Beta 19 does not work every time... You say you haven't changed anything in the PWM and interrupt functionality - maybe at the counter input? Frank |
||||
Geoffg![]() Guru ![]() Joined: 06/06/2011 Location: AustraliaPosts: 3292 |
Yes... you should reduce the amount of code in the interrupt. If I understand the protocol correctly there can be less than 700uS between interrupts which is not enough time to execute all the code that you have in there. Increasing the CPU speed to 48MHz might help but you really need to fix the core problem. Geoff Geoff Graham - http://geoffg.net |
||||
Frank N. Furter Guru ![]() Joined: 28/05/2012 Location: GermanyPosts: 949 |
Hi Geoff, Thanks for the advice! Increasing the CPU speed helps, my old code is now running on Beta 19 (but Beta 16 works without CPU 48). I tried to reduce the code - with the dubious success that the telegrams are received more unstable (many faulty transfers): ' Credits: Tassie Jim for initial decoding code and Gerry Allardice Dim ProgTitle$ = "Lacrosse RAIN DECODER" ' Dim ProgVer$ = "tst_v1.0.3" ' Dim ProgDate$ = "21-Mai-2018" ' '------------------------------------------------------------------------------' ' The Lacrosse RAIN sensor sends code to the console station via 433.92MHz ASK code. ' It can be decoded by using a 433.92 reciever connected to a digital pin eg(16). '*** Option Explicit Option Default NONE '==================================================================================== ' Data Variables '==================================================================================== Dim tick As INTEGER, tock As INTEGER Dim code$,codeinv$,completecode$ Dim INTEGER D01,codeok 'Dim INTEGER TrueA=1 'Dim INTEGER FalseA=0 '==================================================================================== ' Program Initialization '==================================================================================== Print "Starting " + ProgTitle$ + ": " + ProgVer$ + " - " + ProgDate$ PWM 1, 100000, 50 '100000' this is out high resolution timer which gets connected 'to pin 15 SetPin 15, CIN SetPin 16, INTL, blip ' triggers on a high to low transition '==================================================================================== ' Main program loop '==================================================================================== codeok=0 Do If codeok=1 Then Print Mid$( completecode$, 1, 3); Print" "; Print Mid$( completecode$, 4, 4); Print" "; Print Mid$( completecode$, 8, 4); Print" "; Print Mid$( completecode$, 12, 4); Print" "; Print Mid$( completecode$, 16, 4); Print" < "; Print Mid$( completecode$, 20, 4); Print" "; Print Mid$( completecode$, 24, 4); Print" "; Print Mid$( completecode$, 28, 4); Print" "; Print Mid$( completecode$, 32, 4); Print" "; Print Mid$( completecode$, 36, 4); Print" > "; Print Mid$( completecode$, 40, 4); Print" - "; D01 = Val("&b"+Mid$( completecode$, 20, 12)) Print D01 codeok=0 EndIf Loop End Sub blip tock=tick tick = Pin(15) If codeok=0 Then Select Case tick-tock Case > 3000 'end condition If Len(code$)=43 Then completecode$=code$ codeok=1 EndIf code$="" codeinv$="" Case > 2800 'start condition code$="" codeinv$="" Case > 220 'read BITs code$ = code$ + "0" codeinv$= codeinv$+"1" Case > 110 code$ = code$ + "1" codeinv$= codeinv$+"0" Case Else code$="" codeinv$="" End Select If Len(code$)>44 Then 'to much BITs code$="" codeinv$="" EndIf EndIf End Sub This is what I get with this code: Starting Lacrosse RAIN DECODER: tst_v1.0.3 - 21-Mai-2018 100 1010 1010 1100 1001 < 0000 0011 0111 0000 0011 > 0110 - 55 000 1010 1010 1100 1001 < 0000 0011 1000 0000 1011 > 0111 - 56 000 1010 1010 1100 1001 < 0000 0011 1001 0000 0011 > 0111 - 57 000 1010 1010 1100 1000 < 0100 0011 1010 0000 0011 > 1001 - 1082 000 1010 1010 1100 1001 < 0000 1011 1011 0000 0011 > 1010 - 187 000 1010 1010 1100 1000 < 0000 0011 1100 0000 0011 > 1010 - 60 000 1010 1010 1100 1011 < 0000 0011 1101 0000 0011 > 1100 - 61 001 1010 1010 1100 1001 < 0000 0011 1110 0000 0011 > 1101 - 62 000 1010 1010 1100 1000 < 0010 0011 1111 0000 0011 > 1101 - 575 000 1010 1010 1100 1001 < 0000 0100 0000 0000 0101 > 0001 - 64 000 1010 1010 1100 1000 < 0001 0100 0001 0001 0100 > 0001 - 321 000 1010 1010 1100 1000 < 0000 1100 0010 0000 1100 > 0010 - 194 100 1010 1010 1100 1001 < 0000 0100 0111 0000 0100 > 0101 - 71 000 1010 1010 1100 1000 < 0000 0100 1100 0000 0101 > 0100 - 76 100 1010 1010 1100 1001 < 0000 0100 0101 0001 0100 > 0110 - 69 000 1010 1010 1100 1001 < 0000 0100 0110 0000 0100 > 0111 - 70 ...the last number should be 55 to 70... My problem is that I have to wait for the start and end condition, the correct telegram length and the different lengths of "1" and "0"... If I use the variables "TrueA" for "1" and "FalseA" for "0" instead of "codeok=1" and "codeok=0", the transmission no longer works stable at all! How can I make this interrupt routine shorter? ![]() Little update: Case > 3000 'end condition If Len(code$)=43 And codeok=0 Then completecode$=code$ codeok=1 EndIf code$="" codeinv$="" works better than "If codeok=0 Then"... I AM VERY GRATEFUL FOR MORE OF EVERYONE'S TIPS! Frank |
||||
MicroBlocks![]() Guru ![]() Joined: 12/05/2012 Location: ThailandPosts: 2209 |
You could use a FIFO and PUSH values to an array and SHIFT values out of the array. Your interrupt code will then be very small [code] SUB Blip tock=tick tick = Pin(15) Push(tick-tock) END SUB [/code] You would of course have to write some code to make a FIFO or circular buffer, there are lots of examples on internet for that. The reason for doing this is that you spend very little time in the interrupt routine. The processing of the data is done elsewhere. As long as your processing is quick enough the FIFO buffer will not overflow. If there is a pause between messages then that will be great as that time can be used to process it. Microblocks. Build with logic. |
||||
Grogster![]() Admin Group ![]() Joined: 31/12/2012 Location: New ZealandPosts: 9610 |
Very clever idea. I will have to remember that one for when simple flags don't do it for me! ![]() Smoke makes things work. When the smoke gets out, it stops! |
||||
Geoffg![]() Guru ![]() Joined: 06/06/2011 Location: AustraliaPosts: 3292 |
Frank, One possible solution would be to reduce the speed of the PWM. At 100KHz the counting input is kept quite busy counting the input pulses and reducing it to (say) 10KHz would leave more time for the CPU to run your interrupt code. You would also have to reduce the size of the compare constants. For example: Case > 300 'end condition Another help would be to make all variables integers (OPTION DEFAULT INTEGER) as integers are about 25% faster than floats in calculations. Rather than use tick/tock to track the amount of time you can reset the count input to zero just by issuing the SETPIN command again and this would save a little time. For example: Sub blip tick = Pin(15) SetPin 15, CIN If codeok=0 Then Select Case tick For a robust solution I really like MicroBlocks' suggestion. It removes all the intensive code from the interrupt sub. To expand on his code you could use a circular buffer and implement something like this for the interrupt sub. CONST bufsize = 2000 DIM buf(bufsize), bhead = 0, btail = 0 SUB Blip buf(bhead) = Pin(15) SetPin 15, CIN bhead = bhead + 1 IF bhead = bufsize THEN bhead = 0 END SUB Then your main program loop would look something like this: DO IF bhead <> btail THEN tick = buf(btail) btail = btail + 1 IF btail = bufsize THEN btail = 0 SELECT CASE tick Case > 3000 'end condition If Len(code$)=43 Then completecode$=code$ codeok=1 EndIf code$="" codeinv$="" Case > 2800 'start condition ... etc, etc ... With a buffer size of 2000 interrupts you should be able to keep up with a lot of data. There are a lot of examples of circular buffers on the internet. For example: https://en.wikipedia.org/wiki/Circular_buffer Note that it is not feasible to debug this code on the forum. If you want to implement this you will have to work out the details yourself. Geoff Geoff Graham - http://geoffg.net |
||||
Frank N. Furter Guru ![]() Joined: 28/05/2012 Location: GermanyPosts: 949 |
@Geoff & Microblocks: Thank you for your ideas - I will try to put these ideas into practice... (...and thanks to Geoff for pointing out that "OPTION DEFAULT INTEGER" makes the calculations faster...) Frank |
||||
MikeO Senior Member ![]() Joined: 11/09/2011 Location: AustraliaPosts: 275 |
I have been reading with interest all the extra tips regards buffers etc. I have also been experimenting with this sensor but as I was adding it to a project that was already processing various other sensors , communications etc I wasn't keen on trying to add the external(from interrupt) circular buffer idea. I decided to pursue the interrupt processing the pulse timing/storage and found I could reduce the interrupt time by a reasonable amount by making various changes (some of the tips above have also helped). As a matter of interest I found my RF receiver noise (I imagine fairly typical) was keeping the interrupt pretty busy , to the tune of 29-30 seconds per minute! that's 1/3 of the processors time servicing a this sensor to catch 1 result per minute. I was able to reduce this to around 17 secs a substantial improvement by the following, 1 Use If-then instead of Select Case, largest gain. 2 Remove the "Inverted" code$ from the interrupt. 3 Do the Decoding out of the interrupt in the main loop via a flag. 4 Reducing the Data clock also save a few uSecs. Changes reduced the interrupt from ~900 uSecs down to ~500 uSecs. I have not included it in this test code put I plan to disable the interrupt following a successful decode for say 40 secs before it looks for the next transmission leaving the program more resources to handle other tasks. Mike. '------------------------------------------------------------------------------' ' Micromite RF Sensor Decoding ' Credits ' ' Gerry Allardice ' Tassie Jim for initial decoding code ' ' ' ver 1.1 ' Option Explicit Option Default NONE 'Global variables 'Variables for Digoo Temp/Hum Sensor dim integer tick2 , tock2 ,blip2flag dim code2$,digooH$,digooT$ PWM 1, 10000, 50 ' 100uSec interval timer whch gets connected to pin 15 SETPIN 15, CIN SETPIN 16, INTL, blip2 ' triggers low transition 'main Program Loop DO 'Digoo processing if blip2flag=1 then if left$(code2$,1)="1" then if mid$(code2$,17,1)="0" then digooH$=STR$(VAL("&B"+mid$(code2$,30,7))) digooT$=STR$(VAL("&B"+mid$(code2$,17,12))/10) else digooH$=STR$(VAL("&B"+mid$(code2$,30,7))) digooT$="-" +STR$(VAL("&B"+reverse(mid$(code2$,17,12),12))/10) end if blip2flag=0: code2$="" Print time$;" Hum%:";digooH$;" Temp:";digooT$ end if end if LOOP END 'Digoo Sensor Interrupt sub blip2 tock2=tick2 tick2 = PIN(15) if tick2-tock2 > 80 then if len(code2$)=37 then blip2Flag=1 else code2$="" end if elseif tick2-tock2 > 35 then code2$ = code2$ + "1" elseif tick2-tock2 > 15 then code2$ = code2$ + "0" else code2$="" end if 'print pin(15)-tick2 'Debug , to time interrup loop END SUB 'function to "invert" binary string function reverse(in$,l%)as string local x% for x%=1 to l% if mid$(in$,x%,1)="1" then reverse=reverse+ "0" else reverse=reverse+ "1" end if next x% end function Codenquilts |
||||
Frank N. Furter Guru ![]() Joined: 28/05/2012 Location: GermanyPosts: 949 |
Hi Mike, thanks for your very important notes and your code! Frank |
||||
MikeO Senior Member ![]() Joined: 11/09/2011 Location: AustraliaPosts: 275 |
My curiosity got the better of me so I ran an RF Data interrupt using the circular buffer method to store the timings using this code. I used the same method to time the interrupt as I had used previously. (PWM Clock used was same as previously at 10Khz / 100uSec period.) SUB Blip buf(bhead) = Pin(15) SetPin 15, CIN bhead = bhead + 1 IF bhead = bufsize THEN bhead = 0 print pin(15) 'Debug , to time interrup loop END SUB I was surprised at the the results, expecting a huge reduction compared to the code in my previous post but it was not the case. The interrupt timed at ~300uSecs ( my previous code timed at ~500uSecs) so for my purposes anyway it confirmed the gain would not be sufficient to develop the code to use this method. Mike Codenquilts |
||||
PicFan Senior Member ![]() Joined: 18/03/2014 Location: AustriaPosts: 133 |
Hello Geoff ! Please, can you help me with this problem ? Please look on this post. Problem Thank you and best regards ! Wolfgang |
||||
![]() ![]() ![]() ![]() |
![]() |
![]() |
The Back Shed's forum code is written, and hosted, in Australia. | © JAQ Software 2025 |