1. Displaying the spikes

For the output device week, I’m connecting a 20x4 I2C LCD module to my Xiao RP2040 board to display the random spikes that it’s generating. I followed this link to connect Xiao RP2040 with Thonny to program in Micropython, and uploaded two I2C LCD libraries found here onto the RP2040.

Initially, I’ve stuggled a bit as it keeps saying that the SDL pin is wrong, while I’ve confiremd multiple times that it is indeed connected to the right pin. However, after closer inspection, I found out that the pin head is loose and while it’s soldered to the copper ring, the whole ring detached itself from the circuit. After a solder surgery to reconnect them it worked and now I can finally control the LCD.

However, after a quick test file trying to make the LCD display some text, I ran into another issue that the backlight is turning on and off correctly with the code, but nothing is displaying. I asked ChatGPT for debugging advice, and it suggests 2 main direction, one is to change the contrast of the LCD by turning the potentiometer on the back of the I2C module to change the contrast, the other is changing the I2C frequency from 400000 to 100000. I swept through the potentiometer while displaying some texts, and nothing really happened. I then changed the I2C frequency to 100000 and it magically started to display! With texts displayed, turning the potentiometer indeed faded in and faded out the texts as I expected. Out of curiosity, I changed the I2C frequency back to 400000 after I can see the text displaying, and suprisingly it still works now. I don’t understand but I decided to move on and revisit this mystery some other time. For the rest of my codes as 400000 seems to be default, I kept it this way.

I wrote a simple random spike generating code with the help of ChatGPT, which will display 2 randomly generated spike trains that scrolls from rigth to left. I can set the firing probability and this will also be displayed on the screen. The code is as follow:

# Random_spike_LCD.py

import utime
import random
import math
from machine import I2C, Pin
from time import sleep
from pico_i2c_lcd import I2cLcd
i2c = I2C(1, sda=Pin(6), scl=Pin(7), freq=400000)

I2C_ADDR = i2c.scan()[0]
#I2C_ADDR=0x3c
lcd = I2cLcd(i2c, I2C_ADDR, 4, 20)

# Screen settings
cols = 20  # Number of columns on the LCD
rows = 2   # Number of rows on the LCD

# Firing Probability
frprob=0.2
random.seed()

# Initialize spike trains for each row
spike_trains = [[] for _ in range(rows)]

def generate_spike():
    """ Randomly generates spikes for each row. """
    for i in range(rows):
        #if urandom.getrandbits(2)==0:  # Randomly decide to generate a spike
        if random.random() < frprob:
            spike_trains[i].append(cols - 1)  # Start spike at the right edge

def update_spike_trains():
    """ Move spikes left and remove any that go off screen. """
    for row in spike_trains:
        for i in range(len(row)):
            row[i] -= 1  # Move each spike left
        # Remove spikes that have moved off the screen
        row[:] = [x for x in row if x >= 0]

def display_spikes():
    """ Display the spikes on the LCD. """
    lcd.clear()  # Clear LCD before drawing
    for i, row in enumerate(spike_trains):
        for x in row:
            lcd.move_to(x, i)
            lcd.putstr('|')
    lcd.display_on()
    

# Main loop
try:
    while True:
        generate_spike()       # Generate new spikes
        update_spike_trains()  # Move spikes left
        display_spikes()       # Display on LCD
        #update_text()
        #display_text()
        lcd.move_to(4, 2)  # Row index 2 (0-based) for the 3rd row
        lcd.putstr("Random Spikes")
        lcd.move_to(4, 3)  # Row index 2 (0-based) for the 3rd row
        lcd.putstr("FR Prob: " f"{frprob}")
        #lcd.display_on()
        utime.sleep(0.4)       # Adjust speed of animation as needed

except KeyboardInterrupt:
    lcd.clear()

And it worked! I started with something really simple now, and I’ll incorporate the proximity sensing with capacitance from last week to change the firing probability.

The Result

The Result

2. Group Assignment

As a group, we measured the power consumption of the two motors from Marcello’s robot dogs with both a power supply and a multimeter. The two methods gave agreeing result, and showed that driving 2 motors consumes twice as much power compared to 1 motor, and there’s also a small power consumed by the microcontroller itself without driving any motor.

Measuring with a power supply

Measuring with a power supply

Measuring with a multimeter

Measuring with a multimeter