Home  |  Contents 

Microcontroller and PC projects
  Forum Index : Microcontroller and PC projects         Section
Subject Topic: Micromite V5.04.09 Beta 19 Post ReplyPost New Topic
<< Prev Page of 5
Author
Message << Prev Topic | Next Topic >>
MicroBlocks
Guru
Guru
Avatar

Joined: 12 May 2012
Location: Thailand
Online Status: Offline
Posts: 2141
Posted: 21 May 2018 at 8:02pm | IP Logged Quote MicroBlocks

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.


Back to Top View MicroBlocks's Profile Search for other posts by MicroBlocks
 
Frank N. Furter
Guru
Guru


Joined: 28 May 2012
Location: Germany
Online Status: Offline
Posts: 349
Posted: 21 May 2018 at 8:56pm | IP Logged Quote Frank N. Furter

@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
Back to Top View Frank N. Furter's Profile Search for other posts by Frank N. Furter
 
Geoffg
Guru
Guru
Avatar

Joined: 06 June 2011
Location: Australia
Online Status: Offline
Posts: 2290
Posted: 22 May 2018 at 12:27am | IP Logged Quote Geoffg

Frank N. Furter wrote:
or did you have another idea?

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

Edited by Geoffg on 22 May 2018 at 12:28am
Back to Top View Geoffg's Profile Search for other posts by Geoffg Visit Geoffg's Homepage
 
Frank N. Furter
Guru
Guru


Joined: 28 May 2012
Location: Germany
Online Status: Offline
Posts: 349
Posted: 22 May 2018 at 3:34am | IP Logged Quote Frank N. Furter

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
Back to Top View Frank N. Furter's Profile Search for other posts by Frank N. Furter
 
MicroBlocks
Guru
Guru
Avatar

Joined: 12 May 2012
Location: Thailand
Online Status: Offline
Posts: 2141
Posted: 22 May 2018 at 4:10am | IP Logged Quote MicroBlocks

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

SUB Blip
  tock=tick
  tick = Pin(15)
  Push(tick-tock)
END SUB


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.
Back to Top View MicroBlocks's Profile Search for other posts by MicroBlocks
 
Grogster
Guru
Guru
Avatar

Joined: 31 December 2012
Location: New Zealand
Online Status: Offline
Posts: 5722
Posted: 22 May 2018 at 9:56am | IP Logged Quote Grogster

MicroBlocks wrote:
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.



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!
Back to Top View Grogster's Profile Search for other posts by Grogster Visit Grogster's Homepage
 
Geoffg
Guru
Guru
Avatar

Joined: 06 June 2011
Location: Australia
Online Status: Offline
Posts: 2290
Posted: 22 May 2018 at 11:09am | IP Logged Quote Geoffg

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
Back to Top View Geoffg's Profile Search for other posts by Geoffg Visit Geoffg's Homepage
 
Frank N. Furter
Guru
Guru


Joined: 28 May 2012
Location: Germany
Online Status: Offline
Posts: 349
Posted: 22 May 2018 at 5:10pm | IP Logged Quote Frank N. Furter

@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

Edited by Frank N. Furter on 22 May 2018 at 5:13pm
Back to Top View Frank N. Furter's Profile Search for other posts by Frank N. Furter
 
MikeO
Senior Member
Senior Member


Joined: 11 September 2011
Location: Australia
Online Status: Offline
Posts: 175
Posted: 22 May 2018 at 8:55pm | IP Logged Quote MikeO

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
Back to Top View MikeO's Profile Search for other posts by MikeO Visit MikeO's Homepage
 
Frank N. Furter
Guru
Guru


Joined: 28 May 2012
Location: Germany
Online Status: Offline
Posts: 349
Posted: 23 May 2018 at 6:26pm | IP Logged Quote Frank N. Furter

Hi Mike,

thanks for your very important notes and your code!

Frank
Back to Top View Frank N. Furter's Profile Search for other posts by Frank N. Furter
 
MikeO
Senior Member
Senior Member


Joined: 11 September 2011
Location: Australia
Online Status: Offline
Posts: 175
Posted: 23 May 2018 at 7:24pm | IP Logged Quote MikeO

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

Edited by MikeO on 23 May 2018 at 7:55pm


__________________
Codenquilts
Back to Top View MikeO's Profile Search for other posts by MikeO Visit MikeO's Homepage
 


If you wish to post a reply to this topic you must first login
If you are not already registered you must first register

  Search the forums using Google.
<< Prev Page of 5
In the news...
 
Post ReplyPost New Topic
Printable version Printable version
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot delete your posts in this forum
You cannot edit your posts in this forum
You cannot create polls in this forum
You cannot vote in polls in this forum

Powered by Web Wiz Forums version 7.8
Copyright ©2001-2004 Web Wiz Guide

This page was generated in 0.1406 seconds.
Privacy Policy     Process times : 0, 0, 0, 0.14