HomeRaspberry PiCircles are just triangles - using Pico kit to prove it!

Circles are just triangles – using Pico kit to prove it!

Using GeekPi Advanced Raspberry Pi Pico kit to prove it!

There is no denying that the release of the Raspberry Pi Pico, made Micropython even more popular. Board developed primary for Micropython and C++, sparked the interest of makers of all ages. Where there is interest, the manufacturers follow. I ended up with a Raspberry Pi Pico kit (AmazonUK, AmazonUS) put together by GeeekPi, so let’s see what’s inside and how useful it is for makers.

GeeekPi Raspberry Pi Pico kit

I’m always in favour of learning kits, as these give you a sense of direction where GeeekPi kit brings the most popular modules in a single box with a custom PCB board to house the Pico board and break out all GPIO pins in an orderly fashion.

Inside the box

What’s inside Raspberry Pi Pico GeeekPi Kit

Apart from the Raspberry Pi Pico, my kit contains (note that I got the advanced version of the kit, with other configurations available):

There is enough hardware there to keep you busy for some time and get you familiar with different data protocols and ways to command and obtain data.

Raspberry Pi Pico Advanced kit from GeeekPi

Pico breakout board

It’s a handy little board that has a space for a mini breadboard and breaks out all GPIO pins from Raspberry Pi Pico. In addition to that, 3.3V, 5V and GND rails are included and the board comes with 4 push buttons and 4 LEDs that you can use in your project.

There is a buzzer in the corner which you have to connect to GND if it makes random sounds.

Pico guide

The book does a very good job at explaining how individual modules work and goes to fair depth to underline the working principles of boards like MPU6050 or LED matrix. It’s a great read if you want to know how exactly sensors and modules work and report back.

I wish the same could be said for the project part of the book. It’s an illustrated manual of how to get the wires connected with “links” to libraries with the source code. None of the project code is explained or laid out in the teaching manner. If you want to learn how to program, you will be disappointed, as you are expected to understand things by looking at the attached examples.

It’s a shame as what started to be pretty in-depth instructions on sensors and modules ended up skimming over the programming part. If you want to understand how programming logic works, you will need another guide online for that.

My RaspberryPi Pico experiments

I wanted to use Micropython more. GeeekPi provides a GitHub page with project code to mess around with, so I downloaded that and Thonny to get started. The wiring instructions are provided for each module in the booklet, so I decided to work with MPU6050 and neopixel ring.

A long time ago, I have seen someone using a neopixel ring to display which way the board is leaning. I wanted to have a programming crack at it. The demo code for LED ringboard and MPU6050 contains the functions that will get you the data and show you how to set up a state machine on Pico to drive LED, so all I needed to do is to code the logic.

MPU6050 data is processed by the scrip as x(-5, 5) & y(-5,5) ranges, which brings me beautifully to schooldays where algebra and geometry mattered much more than in my life as a 30-something old human being.

I think you can quickly see that I can plot these values on an x/y graph and perform interesting mathematical operations to convert these into the information of which LED ring should light up.

Circles are just triangles in disguise

x² + y²=r²

Pitagora theorem

Circles are many things. They are also triangles hiding in plain sight. Drawing a circle on an XY graph with a radius between the centre point and the coordinate values gives you a lot of data to work with.

On a plane where XY corresponds to tilt and pitch, values can be drawn on a graph where vector direction is represented by the angle between one of the axis and hypotenuse (radius) and the strength is represented by the vector’s length.

  • R= strenght of the lean
  • α= direction of the tilt

To light up the correct LED on a neopixel ring, I need to know the angle between a fixed-line (in my case X-axis) and the hypotenuse. To colour the LED lights accordingly, I need to know how strong is the tilt in that direction (it’s a vector value between values supplied by X and Y).

Armed with that knowledge I can get these values from the following equations:

angle = math.sqrt((roll*roll) + (pitch * pitch))
pixel = math.degrees(math.atan2(roll, pitch))

As the raw values are not compatible with the script, I need to process it further to get ones in line with the library controlling neopixel LEDs. For the angle strength, these are: absolute value, mapped range and not letting the angle (brightness go over 1.0).

To find the correct pixel, I needed radians changed to degrees and round up the division to the nearest integer.

angle_strength = min(convert(math.fabs(math.sqrt((roll*roll) + (pitch * pitch))), 0, 5, 0, 1), 1.0)
pixel = math.ceil(math.degrees(math.atan2(roll, pitch)) / 22.5)

Now the angle will get the values from 0-1 and the pixel will create a 16 element array (from -8 to 8). I accidentally used an unknown, to me, property of python, where the elements would be sorted in such a way, that I don’t have to recalculate the figures again to get 0-16 numbers.

What’s left, is to drive these with existing LED functions based on the value of the angle coming from MPU6050:

if angle_strength < 30:
        pixels_fill(PURPLE)
        pixels_show()
    if angle_strength > 29:
        pixels_fill(BLACK)
        pixels_show()
        pixels_set(pixel, WHITE)
        pixels_show()

Take a closer look at pixels_show() function, to understand the brightness substitution and the convert function which basically maps the value to a new range. These are included in the final version of the code below.

Sample code

from machine import Pin, I2C,
from time import sleep
import mpu6050
import math
import array, time
import rp2

#accelerometer
imu_data = {}
imui2c = I2C(1, scl=Pin(15), sda=Pin(14))
imu = mpu6050.accel(imui2c)

datax = 0
datay = 0
dataz = 0
gAnglex = 0
gAngley = 0
yaw = 0
pitch = 0
roll = 0

#LED setup
NUM_LEDS = 16
PIN_NUM = 6

PURPLE = (180, 0, 255)
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)

@rp2.asm_pio(sideset_init=rp2.PIO.OUT_LOW, out_shiftdir=rp2.PIO.SHIFT_LEFT, autopull=True, pull_thresh=24)

def ws2812():
T1 = 2
T2 = 5
T3 = 3
wrap_target()
label("bitloop")
out(x, 1) .side(0) [T3 - 1] jmp(not_x, "do_zero") .side(1) [T1 - 1] jmp("bitloop") .side(1) [T2 - 1] label("do_zero")
nop() .side(0) [T2 - 1] wrap()

# Create the StateMachine with the ws2812 program, outputting on pin
sm = rp2.StateMachine(0, ws2812, freq=8_000_000, sideset_base=Pin(PIN_NUM))

# Start the StateMachine, it will wait for data on its FIFO.
sm.active(1)

# Display a pattern on the LEDs via an array of LED RGB values.
ar = array.array("I", [0 for _ in range(NUM_LEDS)])

### funtions ###

def pixels_fill(color):
for i in range(len(ar)):
pixels_set(i, color)

def pixels_set(i, color):
ar[i] = (color[1]<<16) + (color[0]<<8) + color[2]

def pixels_show():
dimmer_ar = array.array("I", [0 for _ in range(NUM_LEDS)])
for i,c in enumerate(ar):
r = int(((c >> 8) & 0xFF) * angle_strength)
g = int(((c >> 16) & 0xFF) * 0.01)
b = int((c & 0xFF) * 0.1)
dimmer_ar[i] = (g<<16) + (r<<8) + b
sm.put(dimmer_ar, 8)
time.sleep_ms(2)

def convert(x, in_min, in_max, out_min, out_max):
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min

while True:
imu_data = imu.get_values()
accx = (imu_data['AcX'] ) / 131.0
accy = (imu_data['AcY'] ) / 131.0
accz = (imu_data['AcZ'] ) / 131.0

accAnglex = (math.atan(accy /math.sqrt(pow(accx, 2) + pow(accz, 2))) * 180 / math.pi) - 0.58
accAngleY = (math.atan(-1 * accx / math.sqrt(pow(accy, 2) + pow(accz, 2))) * 180 / math.pi) + 1.58

cTime = time.time()
pTime = cTime
eTime = (cTime - pTime) / 1000

gyx = imu_data['GyX'] + 0.56
gyy = imu_data['GyY'] - 2
gyz = imu_data['GyZ'] + 0.79

gAnglex = gAnglex + gyx * eTime
gAngleY = gAngley + gyy * eTime

roll = 0.96 * gAnglex + 0.04 * accx
pitch = 0.96 * gAngley + 0.04 * accy
#print(roll, pitch)

angle_strength = min(convert(math.fabs(math.sqrt((roll*roll) + (pitch * pitch))), 0, 5, 0, 1), 1.0)
pixel = math.ceil(math.degrees(math.atan2(roll, pitch)) / 22.5)

print(pixel, angle_strength)
if angle_strength < 0.1:
pixels_fill(PURPLE)
pixels_show()
if angle_strength >= 0.1 :
pixels_fill(BLACK)
pixels_show()
pixels_set(pixel, WHITE)
pixels_show()

Final thoughts

Raspberry Pi Pico kit by GeeekPi (AmazonUK, AmazonUS) is for anyone familiar with programming in C++/Microphyton who would like to learn more about interfacing with sensors and modules. Total beginners will feel lost without separate lessons on programming. The advanced kit makes it easy to try modules out and have the basics covered. If you are looking to experiment with Raspberry Pi Pico, then the GeeekPi kit could be for you. Let me know if you have any questions in this Reddit thread.

🆓📈 – See the transparency note for details.

PayPal

Nothing says "Thank you" better than keeping my coffee jar topped up!

Patreon

Support me on Patreon and get an early access to tutorial files and videos.

image/svg+xml

Bitcoin (BTC)

Use this QR to keep me caffeinated with BTC: 1FwFqqh71mUTENcRe9q4s9AWFgoc8BA9ZU

M5Paper

Programable, ESP32 based awesome dev platform with 4.7 e-ink display by M5Stack

More HATs

client-image
client-image

Argon One M.2

Enclose Raspberry Pi 4 inside this great case with custom I/O, cooling and GPIO and M.2 SSD support

More cases on

client-image
client-image

Best Raspberry Pi Projects

How to use Raspberry PI as WOL (wake on lan) server

0
While you could wake up your PC from a mobile directly, having a dedicated server capable of doing so is the best solution. The reason is simple. You can hook up as many devices as you wish with a single endpoint. This is why Raspberry Pi is perfect for this.

How fast Raspberry Pi NAS is?

0
Let's see how fast Raspberry Pi NAS really is?

Argon18: Argon ONE SSD modification

0
Argon One case just got better - now you can boot it from USB without ruining the design thanks to Argon 18: Argon One SSD modification

Slow Internet Warning

0
From time to time my Internet grinds to a stop. Since Raspberry Pi 4 comes with a 1Gbps Ethernet, I decided to take advantage of it and create a reporting system in NodeRED that will monitor and report when the ISP is not keeping the contractual agreements. Works with Alexa, Google Home, Android and Windows 10.

HOW TO...

Raspberry Pi Zero 2 W vs other Zero boards

0
It's time to test the Raspberry Pi Zero 2 W against other Raspberry Pi boards from Zero series: power, WiFi, temperature and core performance

C/C++ and MicroPython SDK for Raspberry Pi Pico on Windows

0
A guide to SDK toolchain for Raspberry Pi Pico and C/C++ , Micropython on Windows.

A comprehensive guide to Grafana & InfluxDB

0
How to use Grafana and InfluxDB on Raspberry Pi for IoT sensors in home automation

How to boot Raspberry Pi 4 from USB

0
How to set up and boot Raspberry Pi 4 from USB drive - headless guide.

Setting Raspberry Pi WiFi without keyboard or cables

0
Getting Raspberry Pi boards connected in seconds