Showing posts with label ESP32. Show all posts
Showing posts with label ESP32. Show all posts

Friday, November 14, 2025

Led filament, a first look

For an index to all my stories click this text

This story is about the rigid led filament. There is also a flexible version which will be discussed in an upcoming story.

I saw on the internet something that looks like a small led strip. They have several names: Led Filament, Cob Led Filament and Edison bulb led parts.


They are meant as ledstrips for use inside filament-lamps like the one above. The yellow strips in the lamp is what I am talking about. They can be bought as tiny led strips.

These are actually really small led strips inside a tubing and have contacts at both sides.


The photo just shows the size of this filament compared to a normal led.
This clearly shows they are slim and long.


The filaments are available in several lengths. I have seen lengths up to 68mm (about 7cm)
For testing purposes I bought a batch of 3.8 cm. Well The advertisement said they were 3.8cm long. And that is correct. However that is inclusive the contacts.


The led filament itself is about 3cm.


And they can be bought in several colors. At the moment of this writing the following colors are available: white, warm white, red, pink, purple, green and blue. They are not like neo-pixels or ordinary led strips. Each strip has only 1 color.

If you are going to buy them just make sure you buy the right ones for your purpose as they are available in 3V and 12V and even higher voltage versions. For our purposes we will be working with the 3V versions. As that is the voltage most of our microcontrollers work with.

Fragile

The tubing that encapsulates the leds feels like plastic. It is not flexible but rigid. The tubing can handle some stress but be aware that it is fragile.


As i wanted to know if it was flexible I bend one of the filaments (a bit) and it broke immediately. So be careful when working with these.
Despite being broken it still worked, what amazed me. Only the leds after where the break was, were working as the picture shows.

VCC and GND

Like stated these are led strips. So they need power. And just like normal leds the power needs to be supplied at the right contacts.


Carefully look at the picture.
At the right side there is a small hole in the contact. That is the VCC side. The other side is GND.
Switching the VCC and GND contacts does not do any harm (yes I tried it) as they are leds. But they just do not work when the power is not connected right.

Current delimiting resistor.

As with all leds these need a current delimiting resistor. More on that later.

Power

On our favorite Chinese website there are several suppliers of these filaments. So I scrolled through a lot of them to find some good specifications.


Most of them stated that the maximum current that could be supplied was 100ma at 3V.

The problem is that no microcontroller that I own can supply that much power from it's IO pins. The Raspberry Pi Pico for example can supply 4ma per IO pin and a maximum of 50ma on all IO pins combined. So the current needed for this filament would fry it. The ESP32 can roll out 40ma maximum at a single IO pin but the total (maximum sum of all IO pins) it can supply is 120Ma. Next to that a prolonged delivery of 40ma on a single pin will overheat and damage the chip. Therefore powering the led filament from a microcontroller is no option.

So I am going to supply the power from a 5V USB phone adapter.
That is 5V so we need to reduce that to 3V. The easiest way to do that is by using a resistor.

To calculate what value the resistor should have we need the following formula.

voltage supplied - voltage desired
-------------------------------------------------------
milliamps


The voltage supplied = 5V
The voltage desired = 3V
The milliamps we need is 50 ma

As you can see I am not powering the strip to the maximum 100Ma.
This gives the following formula:

5V - 3V
----------
50 ma


And 50ma is 0.050 Amps
So that gives 2V / 0,050A is 40 and that makes the value of the resistor 40 Ohm.

So the minimal resistor value is 40 Ohm
Any higher value will do.

Supplying the power.

It is obvious that our ESP8266, ESP32 or Raspberry Pi Pico can never supply such power. So we need an external component for that: a transistor.

The most common used transistor for supplying power is the BC547. This transistor can supply a maximum of 100ma. So we could attach a maximum of 2 led filament strips to 1 of these BC547's. The BC547 is dead cheap. You can get about 50 pieces for 1 USD if you shop around.

If you need more current then use the 2N2222. This transistor is pin compatible with the BC547 but capable of delivering 800ma. Beware that this is under ideal conditions. It would need cooling to achieve that much current. So aim for a lower current like 200-400ma maximum.

I opted for the 2N2222

In real life.

In real life I did some experiments and found that a 100ohm resistor already supplied so much current that the ledstrip was very bright and could even be seen in broad daylight.

Let me do the recalculations for you.

5V - 3V
----------
X ma


This should equal 100 Ohm

So 5-3 / X ma = 100 this gives 2 / 100 = 0.02A = 20 Ma.

Using a 2N2222 transistor I should be able to attach easily 10 led filaments (10 x 20ma - 200ma) to 1 IO pin of the microcontroller.

There is one extra calculation and that is the calculation for the resistor that needs to be attached to the base of the 2N2222 and that defines how much the output will be. I will not bother you with these calculations. But if you mail me I will show these to you in a separate story on this weblog.

The combined calculations.

I will not bother you with the calculations for the base resistor (until you mail me and ask for it). I needed a resistor of 1.5K to 2K for the base of the transistor and for each led filament a resistor of 100 ohm.

2N2222

The 2N2222 has 3 connections E, B and C which are emitter, base and collector.


The Base is connected to a 1.5K resistor and that determines (the gain) the amount of current that will flow from the Emitter (GND) to the Collector. Any load (like our led filament) gets connected to the collector.
So the GND of the led filament is connected to the collector using the current delimiting resistor of 100Ohm.
The Emitter is connected to GND.

I made a test setup first without using a Microcontroller.

Breadboard for the first test.

Here is the breadboard for the first test.


The setup is the same as discussed above.
A resistor of 1.5K is attached to the base of the 2N2222. It is connected to a pushbutton that is connected to VCC. When the pushbutton is pressed some current will flow to the base of the transistor.
The Emitter is just connected to GND.
The Collector is connected through a 100 Ohm current delimiting resistor and from that to GND of the led filament. The VCC of the filament is connected to VCC.
The project is powered by a USB wall adapter, the kind used for phones.

When you push the button, the led filament will light up.
If the filament does not light up, check your connections. Most likely the VCC and GND of the filament have been swapped. Remember that the side where there is a whole in the connection is the VCC side.

That is all.

Attaching a Microcontroller.

The resistor connected to the base of the transistor is calculated at a value that accepts 3.3V from a microcontroller. We can use any microcontroller we like: ESP8266, ESP32 or Raspberry Pi Pico.

For our example we will be using the Raspberry Pi Pico.
The only thing we need to do for our first test is to attach a GPIO pin to the base resistor.
And of course connect the GND of the Pico to the rest of the project.

The Pico will get powered from our computer so:
DO NOT CONNECT THE VCC FROM THE USB POWER ADAPTER TO THE PICO'S POWER RAIL.
CONNECTING BOTH THE PICO WITH THE COMPUTER AND THE EXTRA USB POWER ADAPTER WILL BLAST YOUR PICO AND YOUR COMPUTER TO KINGDOM COME.



The first test program.

This is a small test program that puts the pin GPIO16 at HIGH, waits a second and then puts the pin LOW. The ledstrip will go on for a second, then off for a second and that sequence repeats.

# -------------------------------------------
# simple test for setting filament on and off
# -------------------------------------------
from machine import Pin
import time
filament = Pin(16, Pin.OUT)
while True:
 filament.value(1)
 time.sleep(1)
 filament.value(0)
 time.sleep(1)

Make sure this works before trying the next step.

Dimming the led filament

Now let's see if we can dim the filament with our program.
We can fake the voltage output of a GPIO pin by using PWM.

If you are not aware on how this works I can recommend my books on the Raspberry Pi Pico with MicroPython which you can find at the bottom of this story.

Here is the program that sends a PWM signal to GPIO16.
The led filament is off at first and then slowly gets brighter. When the maximum brightness has been reached it slowly dims till its off again and then the sequence repeats.

# -------------------------------------
# test program for dimming led filament
# with PWM
# -------------------------------------
import machine
import time
filament = machine.PWM(machine.Pin(16))
filament.freq(1000)
while True:
 min = 0
 max = 65536
 for i in range(min,max):
 filament.duty_u16(i)
 time.sleep(.00015)
 time.sleep(1)
 for i in range(max,min,-1):
 filament.duty_u16(i)
 time.sleep(.00015)
 time.sleep(1)

You can adjust the minimum value and the time between steps to your own liking.

Now everything works as expected we can start some real projects with this led filament.

So have fun,
Till next time

Luc Volders

Friday, August 22, 2025

Dweet.cc with MicroPyton

For an index to all my stories click this text

After my story about Dweet.cc and Freeboard I got some mails from readers of that wanted to know how to send data to Dweet.cc and retrieve data from Dweet.cc with MicroPython.

Well here we go.

Sending a dweet to Dweet.cc


The API call I used to send a temperature value to Dweet.cc with the thingname lucstechblog is as follows:

https://dweet.cc/dweet/for/lucstechblog?temperature=25

To use that API call in a MicroPython program you can use the following code:

import network
import urequests
# Router credentials
ssid = "YOUR_ROUTER_NAME"
pw = "PASSWORD"
print("Connecting to wifi...")
# wifi connection
wifi = network.WLAN(network.STA_IF) # station mode
wifi.active(True)
wifi.connect(ssid, pw)
# wait for connection
while not wifi.isconnected():
 pass
# wifi connected
print("Connected. IP: ",str(wifi.ifconfig()[0], "\n"))
# Replace 'lucstechblog' with your actual thing name
# Replace valuename with the name of the value you are sending
# Replace value with the actual value
thingname = 'lucstechblog'
valuename = 'temperature'
value = 25
value = str(value)
url = 'https://dweet.cc/dweet/for/'
url = url + thingname
url = url + "?"
url = url + valuename
url = url + "="
url = url + value
response = urequests.get(url)
print(response.text)
response.close()



That is it.

Put this code in Thonny and press the "run" button. And you will get the next response in the shell:



Of course your IP address will be different.
The response clearly states that the command had succeeded.

I will break the most important part of the code down here for you.

thingname = 'lucstechblog'
valuename = 'temperature'
value = 25
value = str(value)

These are the variables that need to be send to Dweet.cc

I used lucstechblog for the thing name but please use your own thing name. You can choose any name you want but best practice is to make it relevant.
Please be aware that we are sending a public dweet. So anybody in the world that sends a dweet with the same thing name will alter your value.

Then there is a valuename. I used temperature but use something significant like "kitchen-temperature" or "mancave-temperature". For a single dewwt this looks irrelevant but wait till you build a complete home automation system with this.

And then there is the value itself.
If the value is a number (integer or floating point) like in this example you need to convert it into a string like this example shows.

url = 'https://dweet.cc/dweet/for/'
url = url + thingname
url = url + "?"
url = url + valuename
url = url + "="
url = url + value

This is the code that combines all variables into the api call. Just make sure to incorporate the "?" after the thingname and the "=" after the valuename.

I split the code up like this so you can easily put this in your own program and replace the variable names into your own names.

Retrieving a value from Dweet.cc

The code for retrieving a value from the Dweet.cc server is:

https://dweet.cc/get/latest/dweet/for/my-thing-name

In this example it would be:

https://dweet.cc/get/latest/dweet/for/lucstechblog

Let's translate this in a MicroPython program.

import network
import urequests
import ujson
# Router credentials
ssid = "YOUR_ROUTER_NAME"
pw = "PASSWORD"
print("Connecting to wifi...")
# wifi connection
wifi = network.WLAN(network.STA_IF) # station mode
wifi.active(True)
wifi.connect(ssid, pw)
# wait for connection
while not wifi.isconnected():
 pass
# wifi connected
print("Connected. IP: ",str(wifi.ifconfig()[0], "\n"))
# Replace 'my-thing-name' with your actual thing name
thing_name = 'lucstechblog'
url = 'https://dweet.cc/get/latest/dweet/for/'
url = url + thing_name
response = urequests.get(url)
print(response.text)
response.close()

And here is the important part for this program:

url = 'https://dweet.cc/get/latest/dweet/for/'
url = url + thing_name

I splitted the api call in two parts. The first part is the general part and the second part adds your thingname. That is the variable you just created.

And this would gain the following response:




So this proves that it worked.

Decoding the JSON response.

So now we know that this works. However the response is JSON code. And unfortunately that is not direct usable in our program.

Suppose you want to display the temperature on an oled screen, or build a physical thermometer pointer with a servo, or use a bunch of neopixels to display the value like an old-school thermometer.
The JSON code would certainly not be suitable as a value we can work with. We have to decode it.

Here is the complete program that rertrieves the dweet and extracts the value.

import time
import network
import urequests
import ujson
# Router credentials
ssid = "Ziggo2903181"
pw = "ptzbB2ohKbgs7agp"
print("Connecting to wifi...")
# wifi connection
wifi = network.WLAN(network.STA_IF) # station mode
wifi.active(True)
wifi.connect(ssid, pw)
# wait for connection
while not wifi.isconnected():
 pass
# wifi connected
print("Connected. IP: ",str(wifi.ifconfig()[0], "\n"))
# Replace 'my-thing-name' with your actual thing name
thing_name = 'lucstechblog'
#url = 'http://192.168.178.62:8000/get/latest/dweet/for/Kit-pow'
#url = 'http://dweet.me:3333/get/latest/yoink/from/Man-temp'
url = 'https://dweet.cc/get/latest/dweet/for/'
url = url + thing_name
response = urequests.get(url)
print(response.text)
print ("============================================")
# Parse the JSON string
data = ujson.loads(response.text)
# Extract the temperature value
tempvalue = data["with"][0]["content"]["temperature"]
# Display the result
print("Temperature is:", tempvalue)

The important parts are these:

data = ujson.loads(response.text)

We create a variable that decodes the JSON response in its individual parts

tempvalue = data["with"][0]["content"]["temperature"]

There we extract the temperature value and put it into the tempvalue variable.

print("Temperature is:", tempvalue)


And this is where we print the actual value in the shell.

If your JSON code looks different you can use a JSON decoder of which there are several on the internet.

Now the value is stored into the tempvalue variable we can use it for our project.

Decoding JSON structures is a bit puzzling.


Click here to buy my book on the Raspberry Pi Pico W

But then you could buy my book on MicroPython with the Raspberry Pi Pico W that explains it in detail and shows how to get help from a JSON decoder.


Till next time
Have fun

Luc Volders



Friday, August 15, 2025

Freeboard with Dweet.cc

For an index to all my stories click this text.

In a previous story I informed you (as if you did not know) that Dweet.io stopeed working. They suddenly ceased their service and left many users in the dark. Their IOT projects just stopped working. You can read that story here:
https://lucstechblog.blogspot.com/2025/08/dweet-is-dead-long-live-dweet.html


Dweet.io was a great free service and what's more there was a good looking free to use dashboard available. It is called Freeboard and I wrote a few stories about this:
- A first look at Freeboard
- Use Freeboard on Github
- Run your own Freeboard on a Raspberry Pi

And as Dweet.io is not working anymore would I wondered if it would be possible to use Freeboard with one of the rising alternative services.

Altering the Freeboard source code

As written in the story about Dweet.io shutting down, there is an alternative that uses almost the same API calls. The name is Dweet.cc. The only thing you have to do is to alter dweet.io into dweet.cc in your api calls and your ESP8266, ESP32 or Raspberry Pi Pico's can talk to Dweet.cc.


Freeboard has a special datasource accessible called Dweet.io and of course that does notwork anymore.

So I started with adjusting the Freeboard source code.

In the story Run your own Freeboard on a Raspberry Pi I showed how you can download Freeboard and install it on your own PC or a Raspberry Pi.
Freeboard is written in Javascript and that offers opportunities for altering the code.

So I started opening all the HTML, CSS and JSON files in a text editor. I searched for dweet.io and changed it in dweet.cc
Well that did not work. Hmm.

JSON

And then I realized that there was a Datasource with the name JSON.


So I started by sending a simple api call with my browser to Dweet.cc:

https://dweet.cc/dweet/for/lucstechblog?temperature=25

And that worked. I got this as a result:


Ok, that worked.
For retrieving dweets you need to use:

https://dweet.cc/get/latest/dweet/for/my-thing-name

And in this case I had to replace my-thing-name into lucstechblog.

For more information about this, open the index of this weblog and look for Dweet. There are detailed stories on how to use it.
For testing please use your own "thing" name.

So now I had to implement this in Freeboard.
It really is easy and I am going to show you how to get the value for the thing lucstechblog and the value for temp
erature. Again if you want to try this go ahead but please use your own thing name.

First step is to put the get API call into the JSON configuration menu.

When filled in press "SAVE"


Now choose ADD Pane and a smal window opens.


Press the + on the top right side of that window


A pop-up window shows in which you can choose what kind of widget you want. In this example choose Gauge.


In the menu fill the data in as shown.
Pressing the datasource test on the right side gives you the opportunity to walk through the JSON steps.
Press SAVE


And there it is, my simple dashboard with only a gauge.

Now you can add multiple widgets to get your own dashboard up and running with Dweet.cc

If you have any questions that you can not find in the stories on this weblog) do not hesitate to send me a mail.

Conclusion.

Getting Freeboard to work with Dweet.CC was easier than I thought.
Just one problem remains...........Dweet.cc is again a cloud service and I wonder how long before THEY cease operation.........

So my main goal is still to build my own Dweet server that I can run locally. And guess what: I already have that running. It runs on a humble Raspberry Pi3 with a USB stick for memory. The base code was written by a friend of me and I enhanced it with a real database and some other stuff.
I am testing it as we speak.

So keep tuned for further updates on building your own Dweet server. But for now can can get it running with Dweet.cc

Till next time.
Have fun !!

Luc Volders

Friday, August 8, 2025

Dweet is dead, long live dweet

For an index to all my stories click this text.

I fall for it every time, and this time I have had enough.
Read on if you want to know what this is about.

It started a few year ago.

First there was Blynk.I was using Blynk for several projects. You could use their free service on which you could use a limited amount of IOT devices. But you could also install your own Blynk server on a Raspberry Pi and then you could use unlimited devices. And suddenly they switched to Blynk 2. The free server was removed from Github and the accompaning App was removed from Android Play.
Blynk 2 had at that time just a very limited free use. So that was the end of it.

Then there was IFTTT. They suddenly stopped allowing users to use free webhooks. You needed a payed subscription for that. So for using IFTTT with your IOT projects you suddenly needed a payed subscription. So that was the end of it.

Appybuilder, which was an app-building system based on MIT's App Inventor ceased working some time ago.

And the list goes on and on. Several services start giving their customers free access and then suddenly become paid services or quit alltogether.

And now Dweet

I have made some projects with dweet.io and published several stories about this service on this weblog. If you have no clue about what Dweet is read this story first:
https://lucstechblog.blogspot.com/2019/05/dweet-volatile-iot-cloud-service.html

And just January this year they quit too.


This was the message they posted on Twitter (X).
And that really pisses me off as there were lots of users.
So all the projects you made with Dweet.io just stopped working.

And what's more: this also shuts Freeboard down.
For those in the dark: Freeboard is a free IOT dashboard that offers buttons, switches, gauges, leds etc, etc. etc. With this you can make your own IOT dashboard for free but....... it relys on Dweet.io

And to be frank I loved Dweet for being free and it's simplicity.

Dweet users to the rescue.

I was not the only one who was pissed for being disappointed for the umpteenth time.

A few clever users came to the rescue and started a free public Dweet server by themselves. But there is a catch.

dweet.cc
This is the best alternative for dweet.io They claim on their website that at the moment of this writing a total of 1127113 dweets have been send.
It is free and uses nearly the same API.
The catch is that you need to change dweet.io into dweet.cc in the API calls.

dweet.me

Another alternative for dweet.io Dweet.me started 15 March 2025 and claim that they already had more than 1 million dweets on April 24 2025.
On the positive side it is just as free as dweet.io was, and it even offers someting extra. Dweet.io saved the last 5 messages. Dweet.me saves the last 8 messages.
On the negative side the website mentiones it is rate limited, although it does not state what the maximum rate is. And the API calls are more deviant from the dweet.io ones.
This means that you need a bit more altering your projects code.

dweetr.io

This is the last alternative I found. At the moment of this writing the number of dweets used was 57. Not a lot really. And there is a catch. You can only have 2 "things" for free. If you need more you will need a pro subscription. On the positive side: the subscriptions are cheap 25USD for 25 things and 49USD for 50 things for a period of 5 year !!!
The dweetr.io API looks similar to the original dweet.io. You need to change dweet.io into dweetr.io in the API call.

The API calls

I am going to show you the basic API call to send a dweet for the original dweet.io and for the 3 alternatives. So you can see for yourself what changes are needed to use the service.

Send dweet with dweet.io
This will not work anymore, but for comparing purpose only.
https://dweet.io/dweet/for/my-thing-name?hello=world

Send a dweet with dweet.cc
https://dweet.cc/dweet/for/my-thing-name?hello=world

Send a dweet with dweet.me
https://dweet.me:3334/publish/yoink/for/my-thing-name?hello=world

Send a dweet with dweetr.io
http://dweetr.io/dweet/for/my-thing-name?hello=world

As you can see the changes are minimal. Nevertheless you need to alter all your original dweet.io projects.

Which one to choose.

Well that is a difficult question.
Both dweet.cc and dweet.me claim to already have processed more than a million dweets. So it looks like their servers are robust. Dweet.me mentions on their website that it is rate limited and I send them a mail about that. Next to that their API is a bit different so dweet.cc looks like the better choice.
The limitation of just 2 "things" for the free tier makes dweetr.io the least attractive choice.

Mail me if you want the sourcecode for micropython or Arduino code for dweet.cc if you do not get this working. And maybe I am going to do a story about this anyhow.

And Freeboard ?

Freeboard will not work with any of these alternatives right out of the box.
I am going to try to get it working again but that might take some time, if I get it to work at all.........

But I had enough !!!

That's what I wrote at the beginning of this story.
And I am really fed up with companies or private individuals that offer IOT services for free and after a while start charging for subscriptions or quit the service all together.

And like you have seen in this story. There are alternatives to Dweet.io and just like the original they are free to use. But how long will it take for the developer to get fed up with it and shuts the service down, or decides it costs too much bandwidth and needs to charge money for the service.

So what is the real alternative.
Well, to put up your own server at home using a cheap Raspberry Pi or a small (obsolete) PC. That is what I am researching now for my future IOT projects. A Raspberry Zero is quite capable running a dweet alike service and will set you back just a few dollar/euro. So that is a serious option.
I'll keep you up to date through this blog, so keep returning here.

Till next time,

Luc Volders

Friday, July 4, 2025

MicroPython bytecode speed test

For an index to all my stories click this text

In the previous story I wrote how you can make your MicroPython sourcecode unreadable for most users. I did that for trying to protect my program. The way to do this is to convert your program into bytecode. You can read that story here:
https://lucstechblog.blogspot.com/2025/06/protect-your-micropython-sourcecode.html

After I published that story here on my weblog I received a mail from a reader that asked if the bytecode was actually faster as standard MicroPython. The question is valid as bytecode is actually easier to interpret as MicroPython code.

So I did some tests.

Prime numbers

I took a smal program that calculated and printed a few thousand prime numbers. Here is the code.

import time
start_time = time.ticks_ms()
def is_prime(n):
 if n < 2:
 return False
 for i in range(2, int(n ** 0.5) + 1):
 if n % i == 0:
 return False
 return True
count = 0
n = 2
while count < 5000:
 if is_prime(n):
 print(n)
 count += 1
 n += 1
end_time = time.ticks_ms()
elapsed_time = time.ticks_diff(end_time, start_time)
print("Elapsed time:", elapsed_time, "milliseconds")


This code took 32993 miliseconds to run on an ESP8266 with MicroPython V1.20.1.

Then I converted the program to bytecode and it took 32149 microseconds to run. So it was 844 miliseconds (almost a full second) faster.

That is 2.5% faster.

So it is a bit faster but not a lot to gain..

Without print

A lot of time is consumed by the print statement. Print is dependend on the serial communication between the microcontroller and your computer. So let's see what we gain if we leave the print command out.

import time
start_time = time.ticks_ms()
def is_prime(n):
 if n < 2:
 return False
 for i in range(2, int(n ** 0.5) + 1):
 if n % i == 0:
 return False
 return True
count = 0
n = 2
while count < 5000:
 if is_prime(n):
 count += 1
 n += 1
end_time = time.ticks_ms()
elapsed_time = time.ticks_diff(end_time, start_time)
print("Elapsed time:", elapsed_time, "milliseconds")


It's the same program without the print command in the while loop.

The program now took 32385 miliseconds to run.

Again I converted it to bytecode and then it needed 31570 miliseconds to run.
That is 815 miliseconds faster. Again almost a second faster.

And that makes it also 2.5% faster.

This is just a small test but this already shows that bytecode is a bit faster as MicroPython code. So you might gain some speed in certain projects.

Conclusion

Byte code is not real native machine language but an in-between step. This small test already shows that bytecode is a bit faster as MicroPython code. So you might gain some speed in certain projects.

This is not a scientific test just a small test to see if there is any speed to gain. Your results might vary depending on the Microcontroller you are using (ESP8266, ESP32, Raspberry Pi pico etc.) size of the program, libraries used and commands used. So make some tests for yourself.

Till next time,
have fun


Luc Volders

Friday, June 27, 2025

Protect your MicroPython sourcecode

For an index to all my stories click this text

I am/was working on a large project. The project consisted of a microcontroller with some sensors. That microcontroller sends it's data to a dedicated app on an Android phone. Both the microcontroller and the app have to do some complicated calculations.
As I want to show the prototype to several people who might be commercially interested I don't want them to have the opportunity to peek at my software.

I am a lazy developer. So to speed up things I wrote the software for the microcontroller in MicroPython. It works flawless but is not hidden for anyone who connects a computer to the microcontroller. So I had to find a way to hide the program. At least to make it unreadable.

Sidenote.
When you write the programs for your microcontroller with the Arduino IDE it is almost impossible for someone to get the code out of the controller to examine it. Next to that the C++ code you wrote is compiled into machine language by the IDE which is unreadable for most. These two properties keeps your code quite safe. So maybe (when there is time) I will rewrite the program in Arduino language.

How MicroPython works.

MicroPython is an interpreted language. So you write your program in MicroPython and send it to the microcontroller. The code is stored on the microcontroller before it runs. The microcontroller has the MicroPython interpreter on board that converts the code into something the microcontroller understands. So your sourcecode is stored on the Microcontroller ready for anyone to retrieve.

An interpreted language like MicroPython is, is therefore significant slower as the machine language the Arduino IDE produces.
The MicroPython developers found a solution to speed things up.
The MicroPython program is first converted into bytecode. The step between bytecode and machinelanguage is easier and therefore your program will run faster. Still not as fast as pure machinecode, but a lot faster as full MicroPython.

The solution

Bytecode is unreadable by us mere humans. And that offers opportunities for obfuscating the source code.

Here is a simple MicroPython program:



I just wrote this in Thonny and saved it to my computers harddisk.



And this is how the bytecode looks.
I am sure that most people that would get this code in their hands would not have a clue on how to alter this or examine it.

So what we need is a program that takes our MicroPython source code and compiles it into bytecode. And lucky for us this software exists.

Download mpy-cross

The program we need is called mpy-cross and you can get it here:
https://gitlab.com/alelec/mpy_cross/-/packages/7514584

As you can see I used this first when I still was running Windows. You might know that I switched to Linux as my operating system. There is a version of mpy-cross for Linux to and I will discuss how to use that in a future article.

At the time of this writing version V1.20.0 was the latest version. Always check for the latest version and use that.



Click on the latest version and a new window opens.



Scroll down on that page till you find the version for your computer. Mine is:
mpy-cross-v1.20.0-win_x86_64.exe

Download it and install it on your computer in a dedicate directory.
Your computer might give a warning that the software might be unsafe. I tested the package with my virus scanner before installing it and it was totally safe.

My version downloaded and had the name: mpy-cross-v1.20.0-win_x86_64
I altered the name in just mpy-cross

Using mpy-cross

Start with copying your MicroPython program into the directory where the mpy-cross program is.



The program mpy-cross needs to be started from the command line. Just double clicking it will not work.
To achieve this here is a nice trick.



Click on the yellow icon in front of the path to the directory where the mpy-cross program and your python code is.



Now type cmd



And the commandline window opens with the prompt at the right directory.

In my directory there were only two files: mpy-cross and test01.py
And the test01.py file is the file I wanted to compile.

Use the command

mpy-cross test01.py

Just replace the name test01.py with the name your MicroPython source code has.



Press enter and after a (short) while the prompt returns. The time it takes to compile your code depends on the complexity and size of your sourcecode.



And there is the bytecode file. It has the name test01 and looks like a text file but as you have seen in the second picture in this article it is nothing like a text file.

How to use the bytecode file



The file test01.mpy is uploaded to Thonny. Clicking on the name of the file produces an error. MicroPython does not seem to recognise the program code.

This is what you need to do:



Make a program containing just a single line:

import test01

That's all. It will load the file test01 and run it. You can see the result in Thonny's shell.

It does not need to be a program with a single line. The test01.mpy code can be part of a larger program. You just treat it like it is a library.

Concluding

This will not stop people from copying the bootcode file from your MicroPython device. But it will prevent most to analyse your program.

Please be aware that a bytcode file can not be used as main.py to automatically run your program at start-up. So make a one-line file (as discussed above) as your main.py file that calls the bytecode file.

Till next time
have fun

Luc Volders













Friday, April 4, 2025

Linux webserial and webusb problem

For an index to all my stories click this text.

Lately I have been looking into web-based programs that allow to program a Raspberry Pi Pico or ESP32. There are two block-programming based programs called Ioty and Bipes. They work a bit like MIT's App Inventor.

Another thing I have been looking at is Viper Ide. This is an editor for MicroPython programs. I normally use Thonny for creating programs in MicroPython. Thonny is a program that you download onto your computer and then run it. Just like all regular programs.

Viper IDE runs in your browser. You do not need to download anything. Just point your browser to https://viper-ide.org/ and start programming.

This all sounds fine, however I ran into a problem with these web-programs.

Webserial and Webusb

At one time or another you need to connect your microcontroller to your computer with a USB connection. This is to transfer the program from your computer to the microcontroller. And to use USB from your browser, the browser must be able to use Webserial or Webusb. So you can not use Firefox. Chrome does the job.

I am not running a Windows computer (anymore), my system runs Linux. So there is no Chrome browser but there is a derivative called Chromium.


And there I was stuck. Viper IDE told me that it wanted to connect but no compatible devices were found.
As Thonny operated flawless I knew there was nothing wrong with my USB ports. So there must be something wrong with the communication between the webbrowser and the microcontroller.

Safety first

Linux is an operating system that focuses on safety and user rights. Users can not access files, folders and ports without first getting the rights to access them from the administrator (root). And then root can grant access to only read or read and write. This may seem like an annoyance but it makes sure that nobody can get to your data, or delete it, without explicit permission.

And that is what here is the case. We have to grant the webbrowser access to the USB ports. That can be done as follows:


sudo snap connect chromium: raw-usb

This is the command for Kubuntu. Kubuntu is based on Debian so, I presume, this will work on most Debian derivative distributions.

It works

And now it works.


Chromium lists all USB ports and the Raspberry Pico was the first listed,

Play it safe

Although Linux is a really safe operating system it is always better to be safe then sorry. A lot of hackers are around who want to do nasty things on your machine. So what I do is to disconnect the USB port from the web-browser when I am done programming. The command for that is:

sudo snap connect chromium: raw-usb

That's all for now
Till next time


Luc Volders




Subscribe to: Comments (Atom)

AltStyle によって変換されたページ (->オリジナル) /