Simple program crash

RP2040 based microcontroller boards running MicroPython.
Target audience: MicroPython users with an RP2040 boards.
This does not include conventional Linux-based Raspberry Pi boards.
Post Reply
Maximilianus
Posts: 5
Joined: Wed Oct 20, 2021 7:22 pm
Location: Amsterdam

Simple program crash

Post by Maximilianus » Wed Oct 20, 2021 7:31 pm

Hello,

I run a simple program on the Pico that crashes after several minutes.
Printing the memory showed that the free memory is reduced. Until it crashes.

I removed as many lines as possible and found that the multiplying factor (* 0.08) reduces free memory.

How can I solve this?

Thanks.

import machine, utime
import _thread
import micropython

adc_vsys = machine.ADC(3)
adc_0 = machine.ADC(26)
sensor_temp = machine.ADC(4)
potentiometer = machine.ADC(27)
#machine.Pin(26, machine.Pin.IN) #adc0
machine.Pin(29, machine.Pin.IN) #adc3 VSYS
LED = machine.Pin(15, machine.Pin.OUT)
LED_int = machine.Pin(25, machine.Pin.OUT)

cf = 3.3 / (65535)

def LED_thread():
while True:
LED.toggle()
utime.sleep((adc_0.read_u16() * cf)**2 * 0.03)



#_thread.start_new_thread(LED_thread, ())

#print("t °C, VSYS V, adc0 V")
#for cnt in range(100):
while True:
#temp = 27 - (sensor_temp.read_u16() * cf - 0.706)/0.001721
#vsys = 3 * adc_vsys.read_u16() * cf
#print(temp, vsys, adc_0.read_u16() * cf, potentiometer.read_u16()* cf, sep=",")
LED_int.toggle()
#utime.sleep((potentiometer.read_u16() * cf)**2 * 0.08)
#Pauze = ((potentiometer.read_u16() * cf)**2 * 0.08)
Pauze = potentiometer.read_u16() * potentiometer.read_u16() * 0.08
#Pauze = Pauze * 0.08
utime.sleep(1)
print(micropython.mem_info())
Last edited by Maximilianus on Thu Oct 21, 2021 6:23 am, edited 1 time in total.

User avatar
scruss
Posts: 360
Joined: Sat Aug 12, 2017 2:27 pm
Location: Toronto, Canada
Contact:

Re: Simple program crash

Post by scruss » Thu Oct 21, 2021 1:38 am

Your code, indented so we can read it:

Code: Select all

import machine
import utime
import _thread
import micropython

adc_vsys = machine.ADC(3)
adc_0 = machine.ADC(26)
sensor_temp = machine.ADC(4)
potentiometer = machine.ADC(27)
# machine.Pin(26, machine.Pin.IN) #adc0
machine.Pin(29, machine.Pin.IN)  # adc3 VSYS
LED = machine.Pin(15, machine.Pin.OUT)
LED_int = machine.Pin(25, machine.Pin.OUT)

cf = 3.3 / (65535)


def LED_thread():
    while True:
        LED.toggle()
        utime.sleep((adc_0.read_u16() * cf)**2 * 0.03)


#_thread.start_new_thread(LED_thread, ())
#print("t °C, VSYS V, adc0 V")
# for cnt in range(100):
while True:
  #temp = 27 - (sensor_temp.read_u16() * cf - 0.706)/0.001721
  #vsys = 3 * adc_vsys.read_u16() * cf
  #print(temp, vsys, adc_0.read_u16() * cf, potentiometer.read_u16()* cf, sep=",")
    LED_int.toggle()
    #utime.sleep((potentiometer.read_u16() * cf)**2 * 0.08)
    #Pauze = ((potentiometer.read_u16() * cf)**2 * 0.08)
    Pauze = potentiometer.read_u16() * potentiometer.read_u16() * 0.08
    #Pauze = Pauze * 0.08
    utime.sleep(1)
    print(micropython.mem_info()) 

Maximilianus
Posts: 5
Joined: Wed Oct 20, 2021 7:22 pm
Location: Amsterdam

Re: Simple program crash

Post by Maximilianus » Thu Oct 21, 2021 4:40 am

Thank you. Looks better like that!

So this line makes it crash after running some time and filling up memory:
Pauze = potentiometer.read_u16() * potentiometer.read_u16() * 0.08

If I remove the * 0.08 it doesn't crash.

Why can that be?

It is actual the decimal number that fills up memory while running....

Is it a bug??

User avatar
Roberthh
Posts: 3667
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: Simple program crash

Post by Roberthh » Thu Oct 21, 2021 8:29 pm

The decimal constant causes the expression to get float numbers. Float numbers cause a memory allocation. That alone is not a bug.
You could try to use some gc.collect() in the main loop of your code, forcing a garbage collection. Since the RP2040 is effectively a 12 bit ADC, you could rewrite the expression as:

Pauze = potentiometer.read_u16() // 4
Pauze = (Pauze * Pauze * 32) // 25

That causes the whole expression to be integers and stay in the range of a small integer. Note, that the first line reducing Pauze to be a 12 bit quantity must not be merged into the second one, because then Pauze * Pauze might get too large for a small integer.

Maximilianus
Posts: 5
Joined: Wed Oct 20, 2021 7:22 pm
Location: Amsterdam

Re: Simple program crash

Post by Maximilianus » Fri Oct 22, 2021 8:32 am

Thanks for your answer. But it does not make sense to me.

I can use the line: Pauze = 2 * 3
No crash.

But I can't use the line: Pauze = 0.5 * 6
Crash.

In both cases I don't even use the variabele Pauze. It's just a line of code.

This does not seem logic to me.

How can I work around this?

User avatar
Roberthh
Posts: 3667
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: Simple program crash

Post by Roberthh » Fri Oct 22, 2021 8:39 am

The problem per se is strange. Using floats should not crash the memory. But about this line:

Pauze = 0.5 * 6

0.5 * 6 creates a float number. When assigned to Pauze, that will get a float object. If you use:

Pauze = 6 // 2

It will stay integers. Note that 6 / 2 is a float as well. Just try on repl:

type(6 / 2)
type(6 // 2)

to see the difference.

Maximilianus
Posts: 5
Joined: Wed Oct 20, 2021 7:22 pm
Location: Amsterdam

Re: Simple program crash

Post by Maximilianus » Fri Oct 22, 2021 9:20 am

Sorry. It does not work like that.

I need numbers between 0 and 1. The numbers are generated by the ADC input and a mutiplication factor.
With the // it will be 0 or 1 and nothing inbetween.

So what I am testing is ADC input and convert it to the flash frequency of an LED.

utime.sleep(0.08) will work. But the frequency will be fixed.

But not

utime.sleep(8/100) or utime.sleep(8//100)

Is this only on the Pico board?

Maximilianus
Posts: 5
Joined: Wed Oct 20, 2021 7:22 pm
Location: Amsterdam

Re: Simple program crash

Post by Maximilianus » Fri Oct 22, 2021 11:39 am

This one works......Thanks!

Code: Select all

import machine, utime, gc

LED = machine.Pin(15, machine.Pin.OUT)
potentiometer = machine.ADC(27)


while True:
    LED.toggle()
    utime.sleep_ms((potentiometer.read_u16() // 100))
    print(gc.mem_free())
    print(potentiometer.read_u16()//100)

neveregret
Posts: 28
Joined: Sun Aug 08, 2021 5:48 pm

Re: Simple program crash

Post by neveregret » Mon Oct 25, 2021 5:07 am

Is there another solutioun? Because when I add code , When I extend the code line , I need to add gs.collect() or I need to delete gs.collect(). It is so annoying. When code gives memory allocation error, I am trying to add gs.collect() every line because one gs.collect() isn't enough. I am trying with one gs.collect(), if code don't work I am adding another (it is going like this). I am working with MicroPython and CircuitPython.

Code: Select all

import board
import busio
import digitalio
import adafruit_requests as requests
from adafruit_wiznet5k.adafruit_wiznet5k import WIZNET5K
import adafruit_wiznet5k.adafruit_wiznet5k_socket as socket
import gc
from machine import UART,Pin
import time
print("Wiznet5k WebClient Test")
uart = UART(0, rx=Pin(1), tx=Pin(0), baudrate=115200,rxbuf=512)
headers= {"example":"number",}
while True:
    JSON_URL = "http://example.example.com"
    gc.collect()
    cs = digitalio.DigitalInOut(board.GP13)
    gc.collect()
    spi_bus = busio.SPI(board.GP10, MOSI=board.GP11, MISO=board.GP12)
    gc.collect()
    eth = WIZNET5K(spi_bus,cs)
    gc.collect()
    requests.set_socket(socket, eth)
    gc.collect()
    print("Fetching json from", JSON_URL)
    r = requests.get(JSON_URL,headers=headers)
    print(r.json())
    r.close()
    gc.collect()
    print("Done!")

Post Reply