shift register bit shifting considerations [SOLVED]

All ESP32 boards running MicroPython.
Target audience: MicroPython users with an ESP32 board.
Post Reply
LukeVideo
Posts: 22
Joined: Thu May 09, 2019 3:59 pm

shift register bit shifting considerations [SOLVED]

Post by LukeVideo » Thu Jul 11, 2019 8:00 am

Hello,
I have these two functions that i use on different esp32 board with two SN74HC595N shift registers.

Code: Select all

def idle_led(i, data, clock, latch):
    global globalinterrupt_counter
    global total_interrupts_counter
    global reset_counter_val
    global led_count

    zeros = 16- i
    print(zeros)
    for e in range(zeros):
        clock.value(0)
        data.value(0)
        clock.value(1)
        clock.value(0)

    clock.value(0)
    data.value(1)
    clock.value(1)
    clock.value(0)
    for e in range(i):
        clock.value(0)
        data.value(0)
        clock.value(1)
        clock.value(0)

    latch.value(0)
    latch.value(1)
    latch.value(0)
    print('did the idle')


def reset_race(i, data, clock, latch):
    global globalinterrupt_counter
    global total_interrupts_counter
    global reset_counter_val
    global led_count

    global idle_interrupt_counter
    global idle_totalInterrupts_counter
    global interrupt_counter



    # animate leds on race complete

    # keep all leds on for 0.5 seconds
    sleep(0.5)
    for e in range(i):
        #turn all leds off
        for e in range(16):
            clock.value(0)
            data.value(0)
            clock.value(1)
            clock.value(0)
        latch.value(0)
        latch.value(1)
        latch.value(0)
        sleep(0.1)
        # fill leds up
        for e in range(16):
            clock.value(0)
            data.value(1)
            clock.value(1)
            clock.value(0)
            latch.value(0)
            latch.value(1)
            latch.value(0)
            sleep(0.05)
    #turn all leds off
    for e in range(16):
        clock.value(0)
        data.value(0)
        clock.value(1)
        clock.value(0)
    latch.value(0)
    latch.value(1)
    latch.value(0)
    sleep(0.5)
    globalinterrupt_counter = 0
    total_interrupts_counter = 0
    reset_counter_val = 0
    led_count = 0
    idle_interrupt_counter = 0
    idle_totalInterrupts_counter = 0
    interrupt_counter = 0
    print('all zeros')
    
    def update_led(i, data, clock, latch):
    zeros = 16 - i
    print(zeros)
    for e in range(zeros):
        clock.value(0)
        data.value(0)
        clock.value(1)
        clock.value(0)
    for e in range(i):
        clock.value(0)
        data.value(1)
        clock.value(1)
        clock.value(0)
    latch.value(0)
    latch.value(1)
    latch.value(0)
    print('did the leds')

I have an external interupt handling the reset_race and a timer interupt for the idle animation before the race starts. The race is handled by a reed counter on a bike, counting wheel roation calling update_led.

My only problem is that the idle animation has weird behaviour. I have 16 leds and i want each one to turn on one at a time. BUT some don't turn on. With one esp it works, with the second only the first 8 leds turn on then nothing until it loops back to the first. With the third board leds 6,7 15 and 16 don't turn on.

So my question is is their a feature i mist with the shift registers that could create such a weird behaviour, or can i factory reset them ?

All other functions work fine, the reset animation turns all leds on no worries. The wheel rotation counter turns all leds on to... I don't understand why the idle function wouldn't behave the same with three different board with exact same code...??
Last edited by LukeVideo on Mon Jul 29, 2019 7:47 am, edited 1 time in total.

kevinkk525
Posts: 510
Joined: Sat Feb 03, 2018 7:02 pm

Re: shift register bit shifting considerations

Post by kevinkk525 » Thu Jul 11, 2019 8:06 am

I made a more general module to control my shift registers, maybe it helps, it also supports connecting multiple shift registers:

Code: Select all

import machine
from machine import Pin as PyPin # this was actually another Pin class
import gc

gc.collect()


class Mux:
    def __init__(self, shift_pin, store_pin, data_pin, number_multiplexer=1):
        self.shcp = PyPin(shift_pin, machine.Pin.OUT)
        self.stcp = PyPin(store_pin, machine.Pin.OUT)
        self.ds = PyPin(data_pin, machine.Pin.OUT)
        self.__data = bytearray()
        for i in range(0, 8 * number_multiplexer):
            self.__data.append(0)
        self.__size = number_multiplexer
        self.write()

    def write(self):
        self.stcp.value(0)
        for i in range((8 * self.__size) - 1, -1, -1):
            self.shcp.value(0)
            self.ds.value(self.__data[i])
            self.shcp.value(1)
        self.stcp.value(1)

    def __setitem__(self, a, b):
        if b != 1 and b != 0:
            raise ValueError("Value must be 1 or 0")
        self.__data[a] = b

    def __getitem__(self, a):
        return self.__data[a]

    def __delitem__(self, a):
        self.__data[a] = 0

    def set(self, i):
        self.__data[i] = 1

    def clear(self, i):
        self.__data[i] = 0

    def getSize(self):
        """ Get number of pins"""
        return self.__size * 8
You can use it like this:

Code: Select all

import time
leds=Mux(1,2,3)
leds[0]=1
leds[1]=1
leds[3]=1
leds.set(5)
leds.write()

def reset():
    for i in range(0,8):
        leds[i].clear()
    leds.write()

time.sleep(2)
leds.reset()
Kevin Köck
Micropython Smarthome Firmware: https://github.com/kevinkk525/pysmartnode

OutoftheBOTS_
Posts: 662
Joined: Mon Nov 20, 2017 10:18 am

Re: shift register bit shifting considerations

Post by OutoftheBOTS_ » Thu Jul 11, 2019 9:06 am

Using a shift register and standard LEDs is pretty old school. You can do the same job by just using a strip of addressable LEDs (most commonly called Neopixels). The Neopixles wil not only have just on and off but full scale brightness in RGB colour.

LukeVideo
Posts: 22
Joined: Thu May 09, 2019 3:59 pm

Re: shift register bit shifting considerations

Post by LukeVideo » Thu Jul 11, 2019 12:38 pm

I would prefer to keep the code as is as much as possible. My question really is on why the random output for the same function ?
Should i upload a new firmware ??

kevinkk525
Posts: 510
Joined: Sat Feb 03, 2018 7:02 pm

Re: shift register bit shifting considerations

Post by kevinkk525 » Thu Jul 11, 2019 3:24 pm

Just suggesting using a more clearly structured and optimized code. Writing ever latch and clock change just makes your code horrible to read and understand and prone to error.
Kevin Köck
Micropython Smarthome Firmware: https://github.com/kevinkk525/pysmartnode

LukeVideo
Posts: 22
Joined: Thu May 09, 2019 3:59 pm

Re: shift register bit shifting considerations

Post by LukeVideo » Fri Jul 12, 2019 7:37 am

Yes, this code is trash,
But before optimizing it I wanted to know why it isn't consistent on the different devices and shift registers I have. How come reset_race and update_led always work and turn all leds on and off, but the idle_led doesn't always work but if it fails it's always on the same leds but not the same leds on each device... Drives me nuts. If it were to fail with a consistent pattern it wouldn't bother me so much :lol:

Maybe optimizing It will solve the problem after all ?
Let's try !

User avatar
jimmo
Posts: 810
Joined: Tue Aug 08, 2017 1:57 am
Location: Sydney, Australia

Re: shift register bit shifting considerations

Post by jimmo » Fri Jul 12, 2019 10:10 am

I've looked at this a few times now, can't spot anything obvious, but I wondered if maybe seeing the whole program would help. What calls idle_led for example? Are interrupts involved -- is there any way that idle_led is being called via schedule() and therefore interrupting itself? Can you post it on github or something.

Are your different ESP32 boards actually identical models? I don't know much about the ESP32 ecosystem, but I understand there are different types of RAM or something, that could affect timing for interrrupts etc.

That said, I (also) strongly encourage you to adapt to something like Kevin's class, such that you can decouple the code that figures out what state the LEDs should be in from the code that handles the serial data. It'll be so much clearer what's going on. (Or Neopixels, or better, Dotstars (APA102)).

LukeVideo
Posts: 22
Joined: Thu May 09, 2019 3:59 pm

Re: shift register bit shifting considerations

Post by LukeVideo » Mon Jul 29, 2019 6:45 am

OMG, I'm so sorry...
I found that it's a hardware issue. When i fix the board in it's case i squashed some soldering and made a short circuit. So the issue was also happening on the reset animation but so fast the untrained eye couldn't detect it.
I feel bad for wasting your time but with no idea what was going on, I really thought it might be something to do with the way i handled the shift registers in the code.

Back from vacation ready to refactor this as a python class !

Thanks for your time and advise.

Post Reply