Notifications
Clear all

micropython and c

17 Posts
4 Users
7 Reactions
246 Views
byron
(@byron)
No Title
Joined: 7 years ago
Posts: 1264
Topic starter  

I'm sure all are aware that c is much faster than micropython.  This post was just prompted as I've was tinkering with some micropython code I wrote to have some widgets on a small screen, adding another widget and doing some refactoring etc, and a few days ago I posted somewhere a remark to @lee-g who was contemplating having to move to c from python for a self balancing bot project.

My remark was just a reminder that micropython has some speedups relevant to microprocessor use.   As I was refactoring my code I used some of these speedups so I though it may be of interest to see the mp and arduino code speed results. 

I was making use of mapping a value in one range to the equivalent value in another range that I was using to put real data values onto the pixel scale of the screen and I had a small test script to see what speedup I may achieve.  Its only a noddy test, but out of interest I performed the same test in arduino c++ to see how much faster it would be. (a lot faster of course)

I find its vastly preferable to develop in the likes of micropython especially due to not having to go through compile/load cycles, quite a few for my inevitable typo's 😉 .   I would also note that in my micropython test the speed of 20,000 iterations of a function giving us 147922 (fastest) over us 413241(slowest), as the iteration are usually just 1 there was no discernible difference in the program speed at all, and the test of 20,000 was  just to get a timing in the c code that was above us 0

Anyway here is the micopython and the arduino scripts 

import time
import micropython

_amin   = const(-900)
_amax   = const( 900)
_bmin   = const(   0)
_bmax   = const( 480)
_arange = const(_amax - _amin)
_brange = const(_bmax - _bmin)

AVAL = 100  # The value for the A range used for the test.

def mapAtoB_slow(A_val, A_min, A_max, B_min, B_max):
    # Map value from range A to the equivalent value in the range B
    A_range = A_max - A_min
    B_range = B_max - B_min
    return (((A_val - A_min) * B_range) // A_range) + B_min

@micropython.viper
def mapAtoB(A_val:int, A_min:int, A_max:int, B_min:int, B_max:int) ->int:
    # Map value from range A to the equivalent value in the range B
    A_range = A_max - A_min
    B_range = B_max - B_min
    return (((A_val - A_min) * B_range) // A_range) + B_min

# test1 ----------------------------
def test1(aval):
     return mapAtoB_slow(aval, -900, 900, 0, 480)

# test2 ----------------------------
def test2(aval):
    return mapAtoB(aval, -900, 900, 0, 480)

# test 3 ---------------------------
@micropython.viper
def test3(aval:int)->int:
    amin: int = -900
    amax: int = 900
    bmin: int = 0
    bmax: int = 480

    return int(mapAtoB(aval, amin, amax, bmin, bmax))

# test 4 ---------------------------
def test4(aval:int)->int:
    return mapAtoB(aval, _amin, _amax, _bmin, _bmax)

# test 5 ---------------------------
@micropython.viper
def test5(aval:int)->int:
    return int(mapAtoB(aval, _amin, _amax, _bmin, _bmax))

# timer function --------------------
def timeit(func, aval, iters):
    start = time.ticks_us()
    for _ in range(iters):
        bval = func(aval)
    stop = time.ticks_us()
    elapsed_us = time.ticks_diff(stop, start)

    name = getattr(func, "__name__", None)
    # cannot get the funcion name attribute if decorated with @viper
    if not name:
        name = "viper"
    print(name, '- iterations:', iters, '- B range value:', bval, '- Time Taken (us)', elapsed_us)

to_test = [test1, test2, test3, test4, test5]

for test in to_test:
    timeit(test, AVAL, 20_000)

 

#include <Arduino.h>

// These constants mirror your MicroPython const(...) values
static const int _amin   = -900;
static const int _amax   =  900;
static const int _bmin   = 0;
static const int _bmax   = 480;

static const int _arange = _amax - _amin;  // 1800
static const int _brange = _bmax - _bmin;  // 480

static const int AVAL = 100;

// ---- test mapping functions (MicroPython equivalents) ----

// map value in range A to the equivalent in range B
inline int mapAtoB_fast(int A_val, int A_min, int A_max, int B_min, int B_max) {
  int A_range = A_max - A_min;
  int B_range = B_max - B_min;
  return (((A_val - A_min) * B_range) / A_range) + B_min;
}

// test functions - micropython equivalents

int test2(int aval) {
  // return mapAtoB(aval, -900, 900, 0, 480)  (your @viper mapAtoB)
  return mapAtoB_fast(aval, _amin, _amax, _bmin, _bmax);
}

// test3: @viper test3 with local ints
int test3(int aval) {
  int amin = -900;
  int amax =  900;
  int bmin = 0;
  int bmax = 480;
  return mapAtoB_fast(aval, amin, amax, bmin, bmax);
}

// test4: 
int test4(int aval) {
  return mapAtoB_fast(aval, _amin, _amax, _bmin, _bmax);
}

// test5:
int test5(int aval) {
  return mapAtoB_fast(aval, _amin, _amax, _bmin, _bmax);
}

// ---- timeit ----
void timeit(int (*func)(int), int aval, int iters, const char* name) {
  unsigned long start = micros();
  int bval = 0;

  for (int i = 0; i < iters; i++) {
    bval = func(aval);
  }

  unsigned long stop = micros();
  unsigned long elapsed_us = stop - start; // micros() wraps eventually; unsigned handles wrap

  Serial.print(name);
  Serial.print(" - iterations: ");
  Serial.print(iters);
  Serial.print(" - B range value: ");
  Serial.print(bval);
  Serial.print(" - Time Taken (us): ");
  Serial.println(elapsed_us);
}

void setup() {
  Serial.begin(115200);
  delay(1000);

  const int iters = 20000;

  Serial.println("BEGIN benchmarks");
  timeit(test2, AVAL, iters, "test2");
  timeit(test3, AVAL, iters, "test3");
  timeit(test4, AVAL, iters, "test4");
  timeit(test5, AVAL, iters, "test5");
  Serial.println("END benchmarks");
}

void loop() {
  // nothing
}

 

the micropython results were:

test1 - iterations: 20000 - B range value: 266 - Time Taken (us) 413241
test2 - iterations: 20000 - B range value: 266 - Time Taken (us) 310238
viper - iterations: 20000 - B range value: 266 - Time Taken (us) 160199
test4 - iterations: 20000 - B range value: 266 - Time Taken (us) 310234
viper - iterations: 20000 - B range value: 266 - Time Taken (us) 147922

and the arduino results were

test2 - iterations: 20000 - B range value: 266 - Time Taken (us): 4950

test3 - iterations: 20000 - B range value: 266 - Time Taken (us): 4938

test4 - iterations: 20000 - B range value: 266 - Time Taken (us): 4937

test5 - iterations: 20000 - B range value: 266 - Time Taken (us): 4937

Of course no point in trying to mimic the micropython speedups in c++ but just shown for the sake of it.  

No real point is being made in this post, but as I have just done it for my own interest I though I would pop it up.

 



   
Inq and Lee G reacted
Quote
noweare
(@noweare)
Member
Joined: 6 years ago
Posts: 229
 

Thanks for posting this. Using viper is a big improvement over standard micropython. The build, compile, download cycle gets old and i was looking at micropython just to try it out but i really didn't know what the speed difference is. This kind of puts it in perspective for me.



   
ReplyQuote
Inq
 Inq
(@inq)
Rocket Scientist or Space Cadet
Joined: 4 years ago
Posts: 2005
 

@byron,

In my goal to learn Python, I've stuck to using it on a PC or in the Cloud when I have to for the on-line classes.  I know that Python is a interpreted language, aka similar to Basic.  So...

  1. Viper and MicroPython are two distinct/different interpreters that gets loaded onto the micro?
  2. I'd assume the downloaded "engine" is micro dependent - ESP8266, ESP32, Pico, Arduino all are different?
  3. Since C/C++ compiles only what is needed and interpreter pretty much has to load everything in case a script needs it, what is the footprint on a micro?  
  4. Does it have its own IDE on a PC/Mac/Linux or does it just upload out Arduino IDE?  

If you have a recommended article/YT that goes into these type of aspects, that might be easier. 



   
ReplyQuote
byron
(@byron)
No Title
Joined: 7 years ago
Posts: 1264
Topic starter  

@inq 

Your python course will be using python based on CPython which is usually what is referred to when one talks of Python.  There are others, IronPython, jPython and others, but I've not used them though they should all confirm to the python language specification. 

One notable 'other' is micropython which is a cut down version of python though with some microprocessor relevant extras.  As all the various microcontroller boards have different hardware layouts and peripherals there is a micropython version for the different boards.  I give a link to the micropython download site so you can see the range of ports that the official site offers.

https://micropython.org/download/

Micropython is just a c code program and all the c code source is freely available and you can compile your own version, perhaps reducing some of the modules etc. Or indeed including some extra modules.  

Doh, I'm now reminded I forgot in my mp and c comparison post to have another test that includes the c function directly included into a self build of mp.  I will have to do this when I get a chance and post it to complete the comparison.  

Here is a link to the micropython github.

https://github.com/micropython/micropython

AI just told me 'The MicroPython firmware for the Raspberry Pi Pico 2 W uses about 600 kB of flash storage.   I've only hit the limits on smaller boards, though building my python code into a homebrewed micropthon firmware version moves my modules into Flash storage and used less RAM was all that was required.

Although I posted a speed comparison out of interest, and I've always had in mind the relative slowness compared to c, I've never felt any of my stuff was lacking in speed.  Theres a good deal of unused processor cycles in my goto board (pico2W) with 150 million cycles per second.

Micropython is port specific but certainly the speedups of micropython.native and micropython.viper and included for the pico's and esp boards, though I doubt much if you will need them, and I only showed the viper example as a bit of a curiosity.   I expect a c expert such as yourself would throw in an extra c function or two into your home-brewed build in extremity.

The IDE's for python are many and the usual goto's are VSC, Sublime Text, PyCharm etc.  For micropython those can also be used though the usual stater IDE is Thonny.   You cannot use the Arduino IDE for python.

When learning python I liked the Corey Schafer youtube videos: https://www.youtube.com/@coreyms

I may think of some other good links for you, but for now my mind is blank,  the heat of the day has done me in.  Blinking 34 degrees in good old blighty.  Bring back the rainy days.



   
Inq reacted
ReplyQuote
Inq
 Inq
(@inq)
Rocket Scientist or Space Cadet
Joined: 4 years ago
Posts: 2005
 

@byron 

It's my understanding most of the libraries for Python are in C/C++ and get the speed in the portions where its really needed.  I think, for me, the quicker turn-around would might be useful (for me).  Sometimes, I forget what I was going to do next while waiting on the compile and upload.  😆 Depending on perceived slowness, I could always convert to C++ or just let AI translate it.  

Yes, been a miserable summer.  Europe seems to be getting hammered the worst.



   
ReplyQuote
byron
(@byron)
No Title
Joined: 7 years ago
Posts: 1264
Topic starter  

Posted by: @noweare

Thanks for posting this. Using viper is a big improvement over standard micropython. The build, compile, download cycle gets old and i was looking at micropython just to try it out but i really didn't know what the speed difference is. This kind of puts it in perspective for me.

@noweare @lee-g @inq

Ok probably a last remark on this and it's in case my original post needs putting into a more enlighten perspective.  

And as I remarked to @inq in his reply post above I did not go the extra mile to include the way that c and c++ code can be linked into ones own micropython environment and I should really have mentioned this instead of just running the c code as a separate exercise.

To include c code into micropython there is bit of a tedious task to build it into the micropython bindings, and then the c code can either built into one's own micropython firmware build, or it can be built into a .mpy file.  

A mpy file can contain python code and or c/c++ code.  The .mpy file contains precompiled bytecode.  These files or modules can be imported into a micropython script just the same as any .py files.

For this new example I created a .mpy file from c code.  I then use function I created in c the normal way I would use any micropython module.

I created a c function to do the same task as the other python functions (test6).  As you see this shows a  speedup compared to the test1, but its not as fast as a 'normal' python function decorated with @micropython.viper.   And of course  thats still a lot slower than running the c program directly (see the original post).  So here we see that there is an interpreted language overhead and that calling function is quite expensive compared to using compiled code.  

But of course if I really wanted to call a c function that does something meaty I'm not really demonstrating that by repeatedly calling the function in python 20,000 times.  So I create another c program that does the 20,000 iteration directly in the c code so I only have to call the function once.   

I hope I have explained that ok and I post the results of these two extra tests. Test 6 being calling a c function 20,000 times, and test 7 is calling a c function just once and the 20,000 iteration's are done within the c functions code loop.

test1 - iterations: 20000 - B range value: 266 - Time Taken (us) 420899
test2 - iterations: 20000 - B range value: 266 - Time Taken (us) 312669
viper - iterations: 20000 - B range value: 266 - Time Taken (us) 179255
test4 - iterations: 20000 - B range value: 266 - Time Taken (us) 312454
viper - iterations: 20000 - B range value: 266 - Time Taken (us) 167283
test6 - iterations: 20000 - B range value: 266 - Time Taken (us) 292439
test7 - iterations: 1 - B range value: 266 - Time Taken (us) 1935

So just an example that if necessary one can speed up micropython by running some of your own c functions.

Though having said that I've never actually found it necessary to speed up micropython.   My test was really just of interest to see the speedups one could do if needed.

So for the curious I show the amended python code used to run the test that now includes calling the c code modules I imaginatively call testc and testc_iter

I then show the c code I had to produce with the micropython bindings to create a testc.mpy file I could copy to my rpi pico microcontroller. 

Finally, just incase anyone wished to run the micropython code I attach the 2 mpy files that need to reside on the microcontroller. undefined undefined 

import time
import micropython
from testc import testc as mapAtoB_C
from testc_iter import testc as mapAtoB_C_iter

_amin   = const(-900)
_amax   = const( 900)
_bmin   = const(   0)
_bmax   = const( 480)
_arange = const(_amax - _amin)
_brange = const(_bmax - _bmin)

AVAL = 100  # The value for the A range used for the test.

def mapAtoB_slow(A_val, A_min, A_max, B_min, B_max):
    # Map value from range A to the equivalent value in the range B
    A_range = A_max - A_min
    B_range = B_max - B_min
    return (((A_val - A_min) * B_range) // A_range) + B_min

@micropython.viper
def mapAtoB(A_val:int, A_min:int, A_max:int, B_min:int, B_max:int) ->int:
    # Map value from range A to the equivalent value in the range B
    A_range = A_max - A_min
    B_range = B_max - B_min
    return (((A_val - A_min) * B_range) // A_range) + B_min

# test1 ----------------------------
def test1(aval):
     return mapAtoB_slow(aval, -900, 900, 0, 480)

# test2 ----------------------------
def test2(aval):
    return mapAtoB(aval, -900, 900, 0, 480)

# test 3 ---------------------------
@micropython.viper
def test3(aval:int)->int:
    amin: int = -900
    amax: int = 900
    bmin: int = 0
    bmax: int = 480

    return int(mapAtoB(aval, amin, amax, bmin, bmax))

# test 4 ---------------------------
def test4(aval:int)->int:
    return mapAtoB(aval, _amin, _amax, _bmin, _bmax)

# test 5 ---------------------------
@micropython.viper
def test5(aval:int)->int:
    return int(mapAtoB(aval, _amin, _amax, _bmin, _bmax)) 

# test 6 ---------------------------
def test6(aval):
    return mapAtoB_C(aval,_amin, _amax, _bmin, _bmax)

# test 7 ---------------------------
def test7(aval):
    return mapAtoB_C_iter(aval,_amin, _amax, _bmin, _bmax, 20_000)

# timer function --------------------
def timeit(func, aval, iters):
    start = time.ticks_us()
    for _ in range(iters):
        bval = func(aval)
    stop = time.ticks_us()
    elapsed_us = time.ticks_diff(stop, start)

    name = getattr(func, "__name__", None)
    # cannot get the funcion name attribute if decorated with @viper
    if not name:
        name = "viper"
    print(name, '- iterations:', iters, '- B range value:', bval, '- Time Taken (us)', elapsed_us)

to_test = [test1, test2, test3, test4, test5, test6]

for test in to_test:
    timeit(test, AVAL, 20_000)

timeit(test7, AVAL, 1) # test 7 is set to do 20,000 iteration in the c code.
// Include the header file to get access to the MicroPython API
#include "py/dynruntime.h"
#include <stddef.h>

// Helper function to convert a value in A range to an
// equivalent value in a B range.
static mp_int_t testc_helper(
	mp_int_t A_val, 
	mp_int_t A_min,
	mp_int_t A_max,
	mp_int_t B_min,
	mp_int_t B_max)

    {
	mp_int_t A_range = A_max - A_min;
    	mp_int_t B_range = B_max - B_min;
    	return (((A_val - A_min) * B_range) / A_range) + B_min;
    }

// This is the function which will be called from Python,
static mp_obj_t testc(size_t n_args, const mp_obj_t *args)
    {
    // Extract the integer from the MicroPython input object
    mp_int_t A_val = mp_obj_get_int(args[0]);
    mp_int_t A_min = mp_obj_get_int(args[1]);
    mp_int_t A_max = mp_obj_get_int(args[2]);
    mp_int_t B_min = mp_obj_get_int(args[3]);
    mp_int_t B_max = mp_obj_get_int(args[4]);
    mp_int_t iters = mp_obj_get_int(args[5]);
    // Check the correct number of args is given
    if (n_args != 6) 
    {
    mp_raise_ValueError(MP_ERROR_TEXT("expected 6 args"));
    }

    // call the function for specified number of iterations
    mp_int_t result = 0;
    for (int i=0; i<iters; i++)
	{ 
    	result = testc_helper(A_val,A_min,A_max,B_min,B_max);
	}

    // Convert the result to a MicroPython integer object and return it
    return mp_obj_new_int(result);
    }

// Define a Python reference to the function above
static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(testc_obj, 6, 6, testc);

// This is the entry point and is called when the module is imported
mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) {
    // This must be first, it sets up the globals dict and other things
    MP_DYNRUNTIME_INIT_ENTRY

    // Make the function available in the module's namespace
    mp_store_global(MP_QSTR_testc, MP_OBJ_FROM_PTR(&testc_obj));

    // This must be last, it restores the globals dict
    MP_DYNRUNTIME_INIT_EXIT
}

 



   
Inq and Lee G reacted
ReplyQuote
Inq
 Inq
(@inq)
Rocket Scientist or Space Cadet
Joined: 4 years ago
Posts: 2005
 

@byron,

Posted by: @byron

Ok probably a last remark...  (I hope not, Inq)

Thank you for your very thorough and systematic walk-through.

There are several things that are still a little fuzzy for me.  Let me see if I can describe my quandary and see if you already know or can make some educated guesses.

  1. This is just curiosity of how things work:  When doing just Python iterations, the Interpreter is loaded once.  Are you editing the Python source on the micro or is the source on your developing machine and getting uploaded after every little edit?
  2. Can you debug (breakpoints, watch variables) and is it the same like is done when doing Python on and running on a PC or does it require specialized hardware?
  3. Are your C/C++ functions the equivalent of libraries that are loaded up once, say, when the interpreter is first loaded? 

The scenario:  From my reading on self-balancing robots and trying minimize wobble, speed is everything.  I have an acc/gyro sensor coming that supports both higher resolution and higher rates.  I believe it also does the filtering and the Trig and supplies angles so the micro can sample faster and have less work to deal with. 

The point being, speed is critical and I expect my drive libraries and the balancing libraries to be in C/C++.  If these are stable, can they be loaded once and do Python for higher level things like sensing the environment, using AI to make decisions and just directing the drive where to go?

Now for the really interesting thing.  Say, I'm using an ESP32-S3 having two cores.  Can I run the C/C++ self balancing totally in one core AND have the Python interpreter in the second core AND the robot is turned on and balancing by itself.  Can I edit and make changes dynamically on the Python side while the robot is balancing?  Can I do this wirelessly?

I think you can see where I'm going with this. 🤩 

 

Inquisitor



   
ReplyQuote
byron
(@byron)
No Title
Joined: 7 years ago
Posts: 1264
Topic starter  

@inq

A brief response as a starter, as I take a coffee break from refurbishing my lounge thats a bit behind my schedule due my taking it a bit too easy when the weather was too hot.  I need to finish it up before the end of September as the heating needs to be reconnected.  (I do this sort of thing at a lackadaisical pace 😎 )

I think that a self balancing bot may be achievable in mp.  I give a link to a site that seems to be about mp, though its not an official site and seems to exist to put ads on the screen.  But for what its worth I show the link.

https://www.pythontutorials.net/blog/micropython-self-balancing/#google_vignette

I was minded to have a play in building one because I was thinking it is one thing to balance the bot, but probably quite another to balance the bot at the same time its being made to move.  For example one would think that when the bot moves forward it should be made to tilt slightly forward, so it must then be programmed to balance in a different stance than at rest.   

And my little play with seeing what could be speeded up with mp did actually have the self balancing bot mind.   

Also I have not had much of a chance to play with the pico's PIO ability where its use can take the load off the cpu.   In this respect I think it could be very useful for driving stepper motors.   PIO is not anything to do with mp of course, and can be programmed in mp or c.  To program the pico in C/C++ its probably better to use the rpi's C/C++ SDK.  A link to this if interest:

https://www.raspberrypi.com/documentation/microcontrollers/c_sdk.html

So a short spiel on my vague plans and interest in the self balancing bots.  When I get round to it it should be rather fun.

Theres a couple of things I must check to refresh my mind before I properly respond to the questions you pose, so I'll post a bit more later.   If you happen to be minded to check out the  rpi pico for it PIO abilities especially for driving steppers then I would be interest in your views v the esp32  but I'm quite sure that either of the boards would do the job. 

Coffee break done, but now its lunch time, plenty of rest for the lazy. 😀 



   
ReplyQuote
Inq
 Inq
(@inq)
Rocket Scientist or Space Cadet
Joined: 4 years ago
Posts: 2005
 

Posted by: @byron

Also I have not had much of a chance to play with the pico's PIO ability where its use can take the load off the cpu.

I had to look-up PIO and I think I see where it would be advantageous for driving steppers.  I'm also keenly interested in your progress using Python for the balancing part.  I know Python can handle balancing even with plastic toy motors and MPU6050.  I'm wondering if the route I'm taking will show any real world advantages or simply be overkill. 

I'm interested in the hybrid dual core question to get the balancing in one and Python in the other.  The class I'll be taking in AI will be Python and I'd like to leverage that on the ESP32 and hopefully use the vector processor and FPU on the ESP32 to do the Neural-Net (ANN) processing.

That is not meant to be a cattle prod. 😆 I will be rather slow in my progress.  I am expanding the Master Bedroom and we're sleeping in the tiny guest room.  I promised my wife we'd be back in it before I start classes this fall (August 17) and I'm under the gun!

I've finished the sheet-rock, put in the Mini Split and now working on hydronic heating.  I start today covering with Durock and then tiling. 

PXL 20260801 204941799


   
ReplyQuote
robotBuilder
(@robotbuilder)
Member
Joined: 7 years ago
Posts: 2542
 

@inq

Is there any reason not to build your own version of the popular self balancing robots using stepper motors that I see online?

I presume the joystick could be replaced by an onboard Raspberry Pi Pico W running Python code that could implement higher control functions?

https://projecthub.arduino.cc/RolfK/two-wheeled-self-balancing-robot-with-stepper-motor-9ecd74

 



   
Inq reacted
ReplyQuote
byron
(@byron)
No Title
Joined: 7 years ago
Posts: 1264
Topic starter  

@inq

First thing to emphasise is you cant use Python on a microcontroller, and I'm thinking you are alluding to running Python, and not MicroPython when you write  "do Python for higher level things like sensing the environment, using AI to make decisions and just directing the drive where to go". Perhaps Im wrong.

MicroPython is a cut down version of the Python language and this is best illustrated by the following example.  To help understand the example I should mention that most things in Python (and MP) are objects.  

The code below starts by assigning the value of 1 to the variable num. Python will work out that 1 is an integer, thus num will be created as an instance of the int class.  The attributes and methods of the num instance can be seen with the dir() built in function.  So I show the Python and MicroPython methods for the num instance.

Python

>>> num=1

>>> dir(num)

['__abs__', '__add__', '__and__', '__bool__', '__ceil__', '__class__', '__delattr__', '__dir__', '__divmod__', '__doc__', '__eq__', '__float__', '__floor__', '__floordiv__', '__format__', '__ge__', '__getattribute__', '__getnewargs__', '__getstate__', '__gt__', '__hash__', '__index__', '__init__', '__init_subclass__', '__int__', '__invert__', '__le__', '__lshift__', '__lt__', '__mod__', '__mul__', '__ne__', '__neg__', '__new__', '__or__', '__pos__', '__pow__', '__radd__', '__rand__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rlshift__', '__rmod__', '__rmul__', '__ror__', '__round__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__', '__rtruediv__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__trunc__', '__xor__', 'as_integer_ratio', 'bit_count', 'bit_length', 'conjugate', 'denominator', 'from_bytes', 'imag', 'is_integer', 'numerator', 'real', 'to_bytes']

>>> num.is_integer()

True

MicroPython

>>> num = 1

>>> dir(num)

['__class__', 'from_bytes', 'to_bytes']

>>> num.is_integer()

Traceback (most recent call last):

  File "<stdin>", line 1, in <module>

AttributeError: 'int' object has no attribute 'is_integer'

But can do this instead in MP

>>> isinstance(num, int)

True

You can see that a Python program that makes use of class methods not available in MicroPython  will not run in MP.   

So you must decide what code you will run for your 'higher level things' to see if it will be able to run on a microcontroller.  If it has to be Python, then perhaps a rpi zero running rpi os may suffice.  

There is also the Arduino Uno Q that combines SBC running Python with a microcontroller, but you should be careful to read up on this board, or see the DroneBot video before venturing with this board.  I'll just say thus far I'm not too impressed from what I've read.

Onto your 1,2,3 questions:

1)

When using MicroPython you load up the firmware just once.  It will be overwritten when you load a fresher version but the onboard MP file system will remain intact.  You can obliterate it all if you load code from the Arduino IDE.  

MicroPython creates a file system on the board where your MP program reside.   It is possible to run MP code stored on your computer but that probably needs a bit more elucidation, but I leave it at that for now. 

Normally I just create and deleted program files, modules and libraries, whatever you want to call them, directly on the microcontroller boards filesystem MP creates.  The files can be copied to and from the desktop computer.  I usually make edits directly to the file on the microcontroller and try not to forget to copy them back to the pc for backup.   But just know that this can be synchronised a bit better with MicroPythons mpremote facility if desired.

2)

As regards to using a debugger then for MP no, and for Python yes depending on what you think a debugger should be.   But I have never found a need.  Escaping the compile and load cycle,  having a handy REPL, and inserting some simple print statement has been enough.   

However I understand one could say for yes for MP, if you want to use a debugger to debug the underlying c code if you create your own debug version of MP.  I've never gone anywhere near all that malarky so no more to say on that.

Python has an inbuilt pdb module where one can put more debugging type of statements in the Python script, but again I've never found the need.  You can debug Python code in VSC (but is this what you mean by a debugger)

3)

C/C++ functions created as .mpy files, or indeed python files created as .mpy files, or other plain old python .py files only need loading on to the microcontroller once, and would normally be loaded into a /lib directory.  The /lib dir is automatically in the MicroPython search path when importing the files for use in your own program.

Other points:

MicroPython will only run on one core on an ESP32, but can use both cored on a rpi Pico.  I understand the 'other' core on the ESP32 is used by the FreeRTOS.  On the Pico the python Global Interface Lock (GIL) was removed to allow both cores to be used, and for many to fall into the trap of having their code lock up the pico board when using both cores. 😎   It has to be used with care.

A big job you have there, you did mean finish by Aug 17 this year 😮 .   And I have just congratulated myself on a hard days work because I put a second coat of paint on a skirting board and also the wall, just one wall about  8m long that has 2 large window to reduce the paint area.  Still got another 3 wall to go and they have not even got their first coat of paint. I'll still be at it way past Aug 17. (and I'm putting bets that you may be too 😀)



   
ReplyQuote
Inq
 Inq
(@inq)
Rocket Scientist or Space Cadet
Joined: 4 years ago
Posts: 2005
 

Posted by: @robotbuilder

@inq

Is there any reason not to build your own version of the popular self balancing robots using stepper motors that I see online?

I presume the joystick could be replaced by an onboard Raspberry Pi Pico W running Python code that could implement higher control functions?

https://projecthub.arduino.cc/RolfK/two-wheeled-self-balancing-robot-with-stepper-motor-9ecd74

 

No, no reason at all.  I looked at his video and it looks good and scanning through the verbiage, I see lots of good stuff.  I'll probably start out with some kind of manual control.  I've wanted to do something for some time using my phone's accelerometers to have the phone act as a joystick.  Once that's good, then turn to the AI autonomy.

Thanks.

 



   
ReplyQuote
Inq
 Inq
(@inq)
Rocket Scientist or Space Cadet
Joined: 4 years ago
Posts: 2005
 

Posted by: @byron

(and I'm putting bets that you may be too 😀)

Does it count if I put the bed in there?  😆 



   
ReplyQuote
Inq
 Inq
(@inq)
Rocket Scientist or Space Cadet
Joined: 4 years ago
Posts: 2005
 

Posted by: @byron

@inq

First thing to emphasise is you cant use Python on a microcontroller, and I'm thinking you are alluding to running Python, and not MicroPython when you write  "do Python for higher level things like sensing the environment, using AI to make decisions and just directing the drive where to go"...

Thank you for the detailed.  I've already fought a few issues with my on-line classes using Python that some class requires one version and another class another version.  This leads me to believe Python is not very good about keeping backward compatibility, but I didn't actually try to "buck" the class requirements to see.  Its understandable the MP has to be watered down some how just to fit.  Sounds well featured with the on-board file system and editing/running.

But I'm looking forward to using the FPU and vector mathematics built-in the ESP32-S3 for doing the ANN work.  But I expect I'll be using a RasPi zero or better for the high functions anyway and can easily do full Python on it.

 



   
ReplyQuote
Inq
 Inq
(@inq)
Rocket Scientist or Space Cadet
Joined: 4 years ago
Posts: 2005
 

Posted by: @byron

Also I have not had much of a chance to play with the pico's PIO ability where its use can take the load off the cpu.   In this respect I think it could be very useful for driving stepper motors.

I was happily optimizing my stepper drivers using hardware timers and interrupts.  The resolution is at 25 nano-second.  I was pretty happy with what I had and Gemini suggested something that I tried and my performance went down.  I told Gemini about the results of its suggestion compared to my code and it came back and said it was understandable that my solution was better.  

BUT...

It recognized that I was aiming for maximum speed and torque and suggested:

To generate high-frequency step pulses without taxing the CPU or triggering Core 0/1 watchdogs, you can use the ESP32-S3's built-in RMT (Remote Control) peripheral.The RMT functions like a tiny, independent hardware sequencer. You load an array of "pulse durations" into its RAM channel, and the hardware handles toggling the GPIO pins down to the exact nanosecond. Because it requires zero CPU interrupts to toggle the pin states, your stepper motor can reach speeds over 3,000+ RPM while leaving both CPU cores 100% free.

Sounds just like the PIO of the pico you mentioned.  I'm off trying it out.

Inq



   
ReplyQuote
Page 1 / 2