Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Messages - Jason

Pages: 1
Thumby / Re: Flipping Bitmap Images in Thumby IDE
« on: October 19, 2021, 01:17:32 PM »
Other than having the ability to flip bitmaps, is the drawSprite function basically the same as blit then? And many thanks for the image button; I've been using a pixel art website to design my Thumby sprites, so I won't have to draw them a second time now.

It actually calls the blit function after flipping the data, so yes.

Thumby / Re: Flipping Bitmap Images in Thumby IDE
« on: October 19, 2021, 12:13:35 PM »
Hi again,

There is a new 'IMAGE' button in the bitmap builder so you can import images (limit being 72 x 40) to the builder and then export to code.

Also, the
Code: [Select]
drawSprite(...) function allows for mirror on the X & Y axes:
Code: [Select]
thumby.display.drawSprite(inspr, x, y, width, height, mirrorX, mirrorY, key)
See the new Thumby API docs:

Thumby / Re: Is the Random Function broken for anyone else?
« on: October 18, 2021, 10:55:53 AM »
The random number returning the same number should happen both on hardware and in the emulator.

In the case of your game, a more reliable way to seed the random number generator is to feed
Code: [Select]
random.seed(seed) the passed time/ticks using
Code: [Select]
time.ticks_us() or
Code: [Select]
time.ticks_ms() after the user selects a character. It is unlikely that a user will select a character at the same milli or micro second each time (unless maybe they hold down the button from game start each time).

Thumby / Re: Extracting sprites from bitmap data?
« on: October 18, 2021, 10:46:38 AM »
The sprite arrays only define the pixels of the sprite, not any positional data.

The Thumby blit function allows you to draw sprites anywhere on the screen:
Code: [Select]
thumby.display.blit(bitmapData, x, y, width, height, key) where x and y are relative to the top-left of the screen at 0,0 (left to right is +x and top to bottom is +y) but I think you already know that.

One way to do this in a compact way is to make a function that takes a string and position and then draws/blits each character in the string to the screen based on the position. Each character's width would have to be accounted for too, unless it is monospaced and each character is the same width in which case you draw each character at the same offset from the last. We've done some testing and found that this is slow, now we're looking into building a smaller font into the firmware.

Attached is a sketch that will light the LEDS from the base to the top in sequence with 50ms between iterating. After all LEDS are lit, waits 0.5s and turns them back off. LEDS stay lit as the chain progresses.

I hand tweaked the threshold at which the accelerometer needs to move/be jolted before playing the animation. The threshold could potentially need to be lower or higher for each unique piece of hardware. The threshold is low enough now that it sometimes plays the animation as I type on my keyboard.

I removed all other functionally that a typical TinySaber has. Touch does not do anything right now.

Let me know what you think! I'm sure there is plenty of tweaking that needs to be done.

Thumby / Re: A quick question
« on: October 14, 2021, 04:45:44 PM »
You can set a pixel color (either 0 or 1) to be not be drawn/be transparent in the thumby.display.blit() function.

The thumby library wraps the MicroPython framebuffer library, so see this:

For example, the default editor code with the bobbing Thumby sprite has a 32 x 32 black background (the Thumby is drawn in white). Passing '0' as the last parameter in the blit function means all black or 0 pixels will not be drawn.

Try the below code out and look at the blit functions on lines 26 and 29

Code: [Select]
import time
import thumby
import math

# BITMAP: width: 32, height: 32
bitmap0 = (0,0,0,0,0,0,0,0,248,8,232,40,40,40,40,40,40,40,40,40,40,232,8,248,0,0,0,0,0,0,0,0,

    t0 = time.ticks_ms()   # Get time (ms)
    thumby.display.fill(0) # Fill canvas to black

    bobRate = 250 # Set arbitrary bob rate (higher is slower)
    bobRange = 5  # How many pixels to move the sprite up/down (-5px ~ 5px)

    # Calculate number of pixels to offset sprite for bob animation
    bobOffset = math.sin(t0 / bobRate) * bobRange

    # Center the sprite using screen and bitmap dimensions and apply bob offset
    spriteX = int((thumby.DISPLAY_W/2) - (32/2))
    spriteY = int(round((thumby.DISPLAY_H/2) - (32/2) + bobOffset))
    # Draw sprite normally (0 & 1 pixels drawn)
    thumby.display.blit(bitmap0, spriteX, spriteY, 32, 32)
    # Draw sprite halfway overlapping the last sprite but do not draw 0 or black pixels
    thumby.display.blit(bitmap0, spriteX+8, spriteY, 32, 32, 0)

I'll see what I can do

Thumby / Re: Flipping Bitmap Images in Thumby IDE
« on: October 13, 2021, 04:25:43 PM »

We'll definitely consider adding this feature, thanks for the idea.

Other drawing features are also planned: lines, boxes, fill, etc.


Thumby / Re: Emulator?
« on: October 11, 2021, 01:03:45 PM »

There actually is an emulator available in the web IDE:

Just click the "Emulate" button in the code editor

This feature, as well as the web IDE, are in a beta stage of development.

There isn't any documentation/tutorial on how the emulator works just yet.

Let us know about any problems with the IDE or emulator here:


General Discussion / Re: Problems writing to Flash memory
« on: October 07, 2021, 11:12:53 AM »

We don't have any Arduino MKRZERO boards to test the flash shield with.

I assume you are accessing the flash shield pins with a proto shield.

Make sure the following pins are connected from the MKRZERO to the flash shield:
  • MKRZERO SCK    -> flash/proto SCK
  • MKRZERO MISO -> flash/proto MISO
  • MKRZERO MOSI -> flash/proto MOSI
  • MKRZERO digital pin 5  -> flash/proto CS/SS
  • MKRZERO +5v  -> flash/proto VCC
  • MKRZERO GND  -> flash/proto GND

Ensure all connections are separated/not shorting and that they are in the correct spots.

When in the Arduino IDE, verify that the correct board for MKRZERO is selected before upload. This is important, different boards typically have different SPI pin mappings.

Use the below header from the Marzogh SPIMemory library (like in the example you attached) (
Code: [Select]
#include <SPIFlash.h>
I was also able to verify the example works on a TinyDuino + USB shield + flash shield.


Can I get a list of the hardware you are using?

So far I can gather/guess that you have
  • Tinyscreen OLED Tinyshield
  • Adapter Wireling Tinyshield
  • Moisture Sensor Wireling

What processor board are using? You mention "Arduino Pro or Pro Mini" which I assume means you are using the TinyDuino. If that is the case, this will take more investigation.

Anyway, make sure to follow your processor board's tutorial: (use the left panel to find your processor board) so that all relevant libraries and board files get installed.

If you want, follow the tutorial here (should be a copy from the link you provided) using this example project.

Let me know what processor board you have,


This seems related to your other post. Do my replies there help?

General Discussion / Re: "Best" way to send sensor data via BLE?
« on: July 14, 2021, 12:22:12 PM »
Attached is V2 of the example. I would use this one instead of the above since it only allocates memory for packets once instead of every time.

General Discussion / Re: "Best" way to send sensor data via BLE?
« on: July 14, 2021, 11:23:05 AM »

A more efficient way to do this is without using the Arduino String library. Use standard C arrays/buffers instead.

I've made an example project for you, it's attached to this comment as a .zip. The example packs packet IDs, Wireling port number, and the four data vectors you're interested in (accelerometer, gyroscope, compass, & fusion data). Overall, the data is sent in three fragmented packets totaling 52 bytes for each Wireling (so 104 bytes). 52 bytes probably isn't needed, I'll talk about that later, for now, let's talk about the code.

I mentioned that the packets are fragmented. First, packet & Wireling IDs are each 1 byte and can be retrieved from any one packet after being sent; however, the 9-axis library (RTIMU) uses floats to hold sampled data. Each float is 4 bytes. We're sending accelerometer XYZ, gyroscope XYZ, compass XYZ, and fusion XYZ, that's (4*3)*4 = 48 bytes. There's also the one Wireling port ID to send (1 byte), and 3 packet ID bytes (3 bytes). In total there are 48 + 4 = 52 bytes to send in this configuration. Now, as you've found everything needs to be sent in packets of 20 bytes. Because each packet starts with at least an extra byte, and with the way everything lines up, some floats will be split across two packets instead of being contained to one. See the below diagram to see each packet's layout.

| ID0 | PORT | AX[0] | AX[1] | AX[2] | AX[3] | AY[0] | AY[1] | AY[2] | AY[3] | AZ[0] | AZ[1] | AZ[2] | AZ[3] | GX[0] | GX[1] |GX[2] | GX[2] | GY[0] | GY[1] |

| ID1 | GY[2] | GY[3] | GZ[0] | GZ[1] | GZ[2] | GZ[3] | CX[0] | CX[1] | CX[2] | CX[3] | CY[0] | CY[1] | CY[2] | CY[3] | CZ[0] | CZ[1] | CZ[2] | CZ[3] | FX[0] |

| ID2 | FX[1] | FX[2] | FX[3] | FY[0] | FY[1] | FY[2] | FY[3] | FZ[0] | FZ[1] | FZ[2] | FZ[3] |

Looking above, GY[0] + GY[1] are in packet 0 while the other half of the float is in packet 1, keep that in mind. There are some tricks that could be applied to get rid of the fragmentation, but we'll do it the hard way in case more data needs to be added in the future. That's fine though, the attached example takes care of everything when the above data is sent. In any case, I thought it was a good idea to show you how the packets are laid out in case you need to add more data in the future.

I don't know what the receiving side of your project looks like, but keep in mind when rebuilding the floats from each of their 4 bytes, that you need to know how your receiving hardware represents floats as bytes. Google "Endianness" and look at your hardware's datasheet, for both sending and receiving.

For the attached example, my hardware is a TinyScreen+, Wireling adapter shield, BLE Tinyshield, and 2 x 9DOF Wirelings. The Wirelings are connected to ports 0 and 1 on the adapter shield. You're going to be most interested in functions 'SendIMUData()' at line 332, and function 'SpecialUnpackPackets()' at line 237.  Make sure to read the comments in each function. Although the BLE shield is set up, no Bluetooth data is sent in this example by default, but there are some lines in the 'SendIMUData' function you can uncomment to send the packets.

Also, I did not benchmark my example in any way, so see if it works for you in terms of speed. Remove/comment out functions that print to serial when using it in your project, those are there to help you see what's happening in the example. Serial prints slow the program down.

There are more optimizations that can be done. 'malloc' is called for every packet, but since the packets are the same size every time, the memory allocated should only be allocated once and reused every time (a fixed size global buffer). We'll also run into issues with memory fragmentation.

If this still doesn't work, the 9-axis IMU LSM9DS1 on our Wirelings advertises 16-bit output (2 bytes). The RTIMU library must cast this to a float (4 bytes) at some point. If you only needed the accelerometer, gyroscope, and compass data then you could send (2*3)*3 = 18 bytes of data in just one packet! This may mean figuring out how to read the registers of the LSM9DS1 directly or modifying the RTIMU library to be fixed-point and 16-bit (you probably won't be able to do fusion calculations unless that's modified as well to be fixed-point). Or maybe the resulting data from RTIMU can be cast back to 16-bit, we would need to ensure the cast data looks correct. The RTIMU library is supposed to work with many different kinds of IMUs, so floats were probably used to make the library flexible.

There is a lot going on, let me know if you have any problems with the example.

NOTE: See my next reply, the version attached there only allocates memory once for the packets.


I was able to get the TinyScreen+ to work with PlatformIO by changing 'SPI1' to 'SPI' in the Tinyscreen.cpp source file @ line 487.

Also, I added 'SPI' to the platform.ini file under 'lib_deps'. See line 18 of the attached screenshot.

Let me know how this works for you!

Pages: 1
SMF spam blocked by CleanTalk