Page 1 of 1
BLueTooth interrupt
Posted: Fri Dec 04, 2015 2:23 pm
by NicoleN
I am getting MemoryError when trying to control my car's speed via Bluetooth
Code: Select all
pulses = pyb.Timer(2, freq=1000)
pulses.channel(3, pyb.Timer.PWM, pin=pyb.Pin.board.PA2, pulse_width_percent=100)
pulses.channel(4, pyb.Timer.PWM, pin=pyb.Pin.board.PA3, pulse_width_percent=100)
def speed_adj(R_mot_percent,L_mot_percent):
pulses.channel(3, pyb.Timer.PWM, pin=pyb.Pin.board.PA2, pulse_width_percent=R_mot_percent)
pulses.channel(4, pyb.Timer.PWM, pin=pyb.Pin.board.PA3, pulse_width_percent=L_mot_percent)
speed_adj(Right_motor,Left_motor) is working properly from repl. Trying to send a command from my bluetooth which involves the speed_adj() i get:
MemoryError: memory allocation failed, heap is locked
p.ex. when i send the "2" command from bluetooth, will get error at speed_adj(50,50):
Code: Select all
def speed_test():
speed_adj(50,50)
commands = [idle,manual,speed_test]
def command(id):
commands[id]()
def BTread(BTcheck):
if BT.any() == True:
command(BT.readchar())
BTcheck = pyb.Timer(1)
BTcheck.init(freq=100)
BTcheck.callback(BTread)
Re: BLueTooth interrupt
Posted: Fri Dec 04, 2015 6:46 pm
by dhylands
You're not allowed to allocate memory during an interrupt (the timer callback is an interrupt).
@pythoncoder has some preliminary documentation about this:
http://hinch.me.uk/html/reference/isr_rules.html which will get merged into the main documentation, but in the meantime, I highly recommend having a read.
Re: BLueTooth interrupt
Posted: Wed May 18, 2016 5:07 am
by NicoleN
Well, i have read the documentation and tried to fix this in many different ways (using bytearray / readinto() ) but it still doesn't work
Code: Select all
from pyb import UART
BT = UART(4, 9600)
BT.init(9600, bits=8, parity=None, stop=1)
def speed(speed_percent):
pulses.channel(3, pyb.Timer.PWM, pin=pyb.Pin.board.PA2, pulse_width_percent=speed_percent)
pulses.channel(4, pyb.Timer.PWM, pin=pyb.Pin.board.PA3, pulse_width_percent=speed_percent)
def BTread():
if BT.any() == True:
speed(BT.readchar())
BTtimer = pyb.Timer(4)
BTtimer.init(freq=100)
BTtimer.callback(lambda t:BTread())
Any idea will be helpful. I just want when i send a number from my mobile, to run speed(number), using an interrupt.
Re: BLueTooth interrupt
Posted: Wed May 18, 2016 4:53 pm
by pythoncoder
The UART's any() method returns the number of characters pending which will only equate to True if exactly one character is pending. So the code should read:
There was an error in the docs indicating any() returned a boolean, corrected recently.
Re: BLueTooth interrupt
Posted: Wed May 18, 2016 7:36 pm
by deshipu
would have worked too. I can't understand why people write "== True" in their boolean expressions. It's meaningless.
Re: BLueTooth interrupt
Posted: Thu May 19, 2016 2:02 am
by dhylands
There are still a few things wrong with your program (in addition to what's already been mentioned).
Whenever you're dealing with interrupts, I HIGHLY recommend that you add the following 2 lines:
Code: Select all
import micropython
micropython.alloc_emergency_exception_buf(100)
This will pinpoint errors in interrupt handlers, rather than getting a generic MemoryError for everything.
Calling pulses.channel will allocate memory. You should do that once in your main code doing something like:
Code: Select all
pulses = pyb.Timer(2, freq=1000)
ch3 = pulses.channel(3, pyb.Timer.PWM, pin=pyb.Pin.board.X3, pulse_width_percent=0)
ch4 = pulses.channel(4, pyb.Timer.PWM, pin=pyb.Pin.board.X4, pulse_width_percent=0)
def speed(speed_percent):
ch3.pulse_width_percent(speed_percent)
ch4.pulse_width_percent(speed_percent)
While trying to test your code, I also ran into the error that there is no pin named pyb.Pin.board.PA2. There is pyb.Pin.board.X3, and pyb.Pin.cpu.A2.
I was able to get the following code to work:
Code: Select all
import pyb
from pyb import UART
import micropython
micropython.alloc_emergency_exception_buf(100)
BT = UART(4, 9600)
BT.init(9600, bits=8, parity=None, stop=1)
pulses = pyb.Timer(2, freq=1000)
ch3 = pulses.channel(3, pyb.Timer.PWM, pin=pyb.Pin.board.X3, pulse_width_percent=0)
ch4 = pulses.channel(4, pyb.Timer.PWM, pin=pyb.Pin.board.X4, pulse_width_percent=0)
def speed(speed_percent):
ch3.pulse_width_percent(speed_percent)
ch4.pulse_width_percent(speed_percent)
def BTread(tim):
if BT.any():
speed(BT.readchar())
BTtimer = pyb.Timer(4)
BTtimer.init(freq=100)
BTtimer.callback(BTread)
Re: BLueTooth interrupt
Posted: Sun May 22, 2016 7:13 am
by NicoleN
pythoncoder wrote:There was an error in the docs indicating any() returned a boolean, corrected recently.
dhylands wrote:I also ran into the error that there is no pin named pyb.Pin.board.PA2
I use a 2015/10 firmware version. I have recently tried to update but i had problems with pin names etc, so i downgraded again. In my board, UART's .any() returns Boolean, no matter how many characters are waiting.
dhylands wrote:Calling pulses.channel will allocate memory
You are the best! Thanks!
Re: BLueTooth interrupt
Posted: Sun May 22, 2016 7:28 am
by dhylands
NicoleN wrote:In my board, UART's .any() returns Boolean, no matter how many characters are waiting.
If you use the form:
then it will work regarless of whether any returns a boolean or an integer.
Re: BLueTooth interrupt
Posted: Mon May 23, 2016 4:54 am
by pythoncoder
@NicoleN If I remember correctly the behaviour of any() was changed last year, with the docs lagging behind. Current firmware returns an integer. In general it's a good idea to use current firmware: I'm puzzled about the problem you have with current firmware and pin names. What board are you using? Perhaps you could elaborate?