1. Black Friday Sale - 50% off

    B4A Standard for $29 instead of $59!
    Buy Now
    Dismiss Notice

B4R Question NumberFormat problem

Discussion in 'B4R Questions' started by kolbe, May 22, 2017.

  1. kolbe

    kolbe Active Member Licensed User

    I'm working with a Feather M0 and when I call NumberFormat twice the program halts. Using a timer and and leds I know the execution stops. I've checked StackBufferUsage and it is only 13 after the first call so I don't think I'm running out of memory. In the case below I'm using the AdafruitSSD1306 library but I first noticed this problem using it with logs. I comment out the first line and it works. Comment out the second and it works. Only when both are called that the code crashes.

    Any ideas?

    Code:
    oled.GFX.DrawText(NumberFormat(temp(counter),1,1)).DrawText(" F").DrawText(CRLF)
    oled.GFX.DrawText(
    NumberFormat(humid(counter),1,1)).DrawText(" %")
     
  2. Erel

    Erel Administrator Staff Member Licensed User

    Which board are you using? It is worth testing it with a higher StackBufferUsage value.

    You should also check the value of Log(AvailableRAM).
     
  3. kolbe

    kolbe Active Member Licensed User

    It's an Adafruit Feather M0 Bluefruit LE. So it is using the ATSAMD21G18 ARM Cortex M0 processor. This is the same as the Aurduino Zero.

    I tried both things you suggested without luck. I have about 25K of free RAM. This chip has 32K RAM. AvailabeRAM doesn't work but this alternative does. Increasing the StackBufferUsage doesn't help either.

    I'm wondering if it has to do with memory usage differences listed at the bottom of the link above.
     
  4. Erel

    Erel Administrator Staff Member Licensed User

    It does look like a memory issue.
    What is the output of Log(temp(counter)) and Log(humid(counter)) ?

    Can you post the relevant sub?
     
  5. kolbe

    kolbe Active Member Licensed User

    Here's the code.

    Here's output from the code below

    Code:
    #
    #Region Project Attributes
        
    #AutoFlushLogs: True
        
    #CheckArrayBounds: True
        
    #StackBufferSize: 600
    #End Region

    Sub Process_Globals
        
    'These global variables will be declared once when the application starts.
        'Public variables can be accessed from all modules.
        Public Serial1 As Serial
        
    Private timer1 As Timer
        
    Private master As WireMaster
        
    Private const SLAVE_ADDRESS As Byte = 64
        
    Private temp(300As Float
        
    Private humid(300As Float
        
    Private counter=0 As Int
        
    Private pin13 As Pin
        
    Private oled As AdafruitSSD1306
        
    Private free As Int
    End Sub

    Private Sub AppStart
        Serial1.Initialize(
    115200)
        
    Log("AppStart")
        master.Initialize
        pin13.Initialize(
    13, pin13.MODE_OUTPUT)
        timer1.Initialize(
    "Timer1_Tick"1000)
        oled.InitializeI2C(
    10,0x3c)
        timer1.Enabled = 
    True
        RunNative(
    "FreeRam"Null)
        
    Log(free)
    End Sub

    Sub Timer1_Tick
        timer1.Enabled=
    False
        pin13.DigitalWrite(
    True)
       
        
    Dim readbyte(3As Byte
        
    Dim writebyte(1As Byte
       
        writebyte(
    0)=0xe3 'read temp register
       
        master.WriteTo2(SLAVE_ADDRESS,
    True,writebyte)
        Delay(
    50)
        readbyte = master.RequestFrom(SLAVE_ADDRESS,
    3)
        
    If readbyte.Length=3 Then
            
    Dim partial1=(Bit.ShiftLeft(Bit.And(readbyte(0),0xff),8)+Bit.And(readbyte(1),0xfc)) As Int
            
    Dim partial2=-46.85+(175.72*(partial1/65536)) As Float
        
    Else
            
    'Log(readbyte.length)
        End If
       
        Delay(
    50)
       
        writebyte(
    0)=0xe5 'read humidity register
        master.WriteTo2(SLAVE_ADDRESS,True,writebyte)
        Delay(
    50)
        readbyte = master.RequestFrom(SLAVE_ADDRESS,
    3)
        
    If readbyte.Length=3 Then
            
    Dim partial3=(Bit.ShiftLeft(Bit.And(readbyte(0),0xff),8)+Bit.And(readbyte(1),0xfc)) As Int
            
    Dim partial4=-6+(125*(partial3/65536)) As Float
        
    Else
    '        Log(readbyte.length)
        End If
       
    '    Log(NumberFormat(partial2*1.8+32,1,1),",",Round(partial4))
       
        
    If counter >= 299 Then
            temp(counter)=partial2*
    1.8+32
            humid(counter)=partial4
           
            
    Dim sum=0 As Float
            
    For i=0 To 299
                sum=sum+temp(i)
            
    Next
            
    Dim avgtemp=(sum/300As Float
           
            sum=
    0
            
    For i=0 To 299
                sum=sum+humid(i)
            
    Next
            
    Dim avghumid=(sum/300As Float
           
            counter=
    0
            
    Log(avgtemp,",",avghumid)
           
        
    Else
            temp(counter)=partial2*
    1.8+32
            humid(counter)=partial4
           
    '        Log(counter)
            Log(temp(counter))
            
    Log(humid(counter))
            oled.ClearDisplay
            oled.GFX.SetCursor(
    0,0)
            oled.GFX.ConfigureText(
    2,oled.WHITE,False)
            oled.GFX.DrawText(
    NumberFormat(temp(counter),1,1)).DrawText(" F").DrawText(CRLF)
            oled.GFX.DrawText(temp(counter)).DrawText(
    " F").DrawText(CRLF)
    '        oled.GFX.DrawText(NumberFormat(humid(counter),1,1)).DrawText(" %")
            oled.Display
            counter=counter+
    1
        
    End If
       
        pin13.DigitalWrite(
    False)
        timer1.Enabled=
    True
       
        RunNative(
    "FreeRam"Null)
        
    Log("-")
        
    Log (free)
        
    Log(StackBufferUsage)
        
    Log("--")
    End Sub

    #if C

    extern "C" char *sbrk(int i);

    void FreeRam (B4R::Object* o) {
      char stack_dummy = 0;
      b4r_main::_free = &stack_dummy - sbrk(0);
    }

    #End if
     
  6. Erel

    Erel Administrator Staff Member Licensed User

    Note that you don't need to disable and enable the timer. It will never fire while the code is executing. It is better to remove it.

    Does it crash if you call Log(NumberFormat(humid(counter),1,1)) ?
     
  7. kolbe

    kolbe Active Member Licensed User

    Understood for the timer. I got in the habit of doing this for Android stuff.

    Yes if I uncomment that line it crashes. Don't know if it helps but after the crash I need to put the board in bootloader mode to be able the upload again.
     
  8. kolbe

    kolbe Active Member Licensed User

    Didn't understand correctly your question perhaps. As far as I can tell... in the timer sub using NumberFormat once is fine. Once I call it again it crashes. It doesn't seem to make a difference if the second call is in a log or in for the lcd. I'll make a few more tests.
     
  9. kolbe

    kolbe Active Member Licensed User

    After a few more tests.

    This doesn't work.
    Code:
    Log(NumberFormat(10.4545,1,1))
    Log(NumberFormat(20.4545,1,1))
    This does work.
    Code:
    Log(NumberFormat(2,1,1))
    Log(NumberFormat(20.4545,1,1))
    This doesn't work
    Code:
    Log(NumberFormat(10.4545,1,1))
    Log(NumberFormat(2,1,1))
    this works
    Code:
    Log(NumberFormat(2,1,1))
    Log(NumberFormat(2,1,1))
    Log(NumberFormat(10.4545,1,1))
    doesn't work
    Code:
    Log(NumberFormat(2,1,1))
    Log(NumberFormat(2,1,1))
    Log(NumberFormat(10.4545,1,1))
    Log(NumberFormat(2,1,1))
    doesn't work
    Code:
    Log(NumberFormat(10,1,1))
    Log(NumberFormat(10.4545,1,1))
    this works
    Code:
    Log(NumberFormat(9,1,1))
    Log(NumberFormat(10.4545,1,1))
    Incidentally, taking out the timer enable true/false lines does change the rate the leds blink. If I want the time between running the sub to be as close to 1s as posible I can do what I did. Otherwise the time it takes to run the sub is subtracted from the time the sub is run. In this case 214 ms to run the sub so the sub would be run every 786 ms. Now maybe you are saying that doing this is not the best idea for code backend reasons.
     
  10. kolbe

    kolbe Active Member Licensed User

    Trying a workaround discovered this too.

    The code below outputs

    73.35
    73.3467

    Then it crashes.

    Why does str1 round off? Byte alignment problems?
    Code:
    Dim str1="" As String
    str1 = temp(counter)
    Log(str1)
    Log(temp(counter))
    Log(bconv.SubString2(str1,0,2))

    also this works
    Code:
    Dim str1="" As String
    str1 = temp(counter)

    but this doesn't
    Code:
    Dim str1="" As String
    str1 = temp(counter)
    Dim str2="" As String
    str2 = humid(counter)
     
    Last edited: May 22, 2017
  11. Erel

    Erel Administrator Staff Member Licensed User

    The best solution is to remove all the delay calls and use CallSubPlus instead to call the next sub each time.
    However lets first debug the memory issue.

    Can you reproduce this memory issue on an Arduino or ESP8266?
     
  12. kolbe

    kolbe Active Member Licensed User

    Don't have a ESP8266 but it does work on a Feather 32u4 which runs on a ATmega32u4. Hope to have a ESP32 soon but not yet.
     
  13. Erel

    Erel Administrator Staff Member Licensed User

    Can you upload a program that crashes (and doesn't need any additional hardware)? I will test it on the ESP8266.
     
  14. kolbe

    kolbe Active Member Licensed User

    Here you go.
     

    Attached Files:

  15. Erel

    Erel Administrator Staff Member Licensed User

    Works fine on ESP8266.

    Try this:
    Download the attached Define-Template.h and put it in the projects Files folder.

    It should show this message during compilation:
    Parsing code. (0.00s)
    Compiling code. (0.02s)
    Building project (0.02s)
    Using custom define-template file.

    It sets the byte alignment to 8.
     

    Attached Files:

  16. kolbe

    kolbe Active Member Licensed User

    Seems to fix the problem. I'll try some more cases soon.
     
Loading...
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice