Page 1 of 1

Make a counter

Posted: Wed Jun 09, 2021 1:22 pm
by james_saunders2
Hi, I'm new to micropython and the pi pico board, but I'm developing activities for students using basic components, a pi pico and Thonny.
I'm trying to develop a programme that essentially uses a single-digit 7-segment display to count to 5 from 0, and have attached my code so far which works but would like some suggestions on how to make this programme take up fewer lines. Also... is it possible to define the functions for all the numbers in a separate file and then call them in my final counter script?
Apologies if this doesn't make sense - very new to it all!

Code: Select all

import machine
import utime

#The next 8 lines of code assigns each LED to the correct pin on the pico board
dp = machine.Pin(16, machine.Pin.OUT) 
a = machine.Pin(0, machine.Pin.OUT)
b = machine.Pin(1, machine.Pin.OUT)
c = machine.Pin(2, machine.Pin.OUT)
d = machine.Pin(3, machine.Pin.OUT)
e = machine.Pin(4, machine.Pin.OUT)
f = machine.Pin(5, machine.Pin.OUT)
g = machine.Pin(6, machine.Pin.OUT)

def off(): # defines a function for the off state
    # this allows the code to reset the display between each number
    a.value(0)
    b.value(0)
    c.value(0)
    d.value(0)
    e.value(0)
    f.value(0)
    g.value(0)
    dp.value(0)

def zero(): # defines the zero state
    a.value(1)
    b.value(1)
    c.value(1)
    d.value(1)
    e.value(1)
    f.value(1)
    
def one():
    b.value(1)
    c.value(1)

def two():
    a.value(1)
    b.value(1)
    g.value(1)
    e.value(1)
    d.value(1)
    
def three():
    a.value(1)
    b.value(1)
    g.value(1)
    c.value(1)
    d.value(1)
    
def four():
    b.value(1)
    g.value(1)
    f.value(1)
    c.value(1)
    
def five():
    a.value(1)
    f.value(1)
    g.value(1)
    c.value(1)
    d.value(1)
    
off()    
zero()
utime.sleep(1)
off()
one()
utime.sleep(1)
off()
two()
utime.sleep(1)
off()
three()
utime.sleep(1)
off()
four()
utime.sleep(1)
off()
five()

Re: Make a counter

Posted: Wed Jun 09, 2021 2:30 pm
by hippy
One option for minimising lines of code is to define your segment mappings as bits in a byte ...

Code: Select all

from machine import Pin

out = [None] * 8
for n in range(7):
  out[n] = Pin(n, Pin.OUT)
out[7] = Pin(16, Pin.OUT)

def Output(bits):
  for n in range(8):
    out[n].value((bits >> n) & 1)

#                       .GFEDCBA
def Off()   : Output(0b_00000000)
def Zero()  : Output(0b_00111111)
def One()   : Output(0b_00000110)
def Two()   : Output(0b_01011011)
def Three() : Output(0b_01001111)
etc

Re: Make a counter

Posted: Fri Jun 11, 2021 9:28 am
by james_saunders2
Hi, so I used your suggestion for the counter code. Thanks!
I'm now trying to work out a way to assign the various functions to one matrix so that I can call each successive function at a specific time, e.g. when a button is pressed. I tried the following:

Code: Select all

from machine import Pin
import utime
#            A   G   F   E   D   C   B   DP
GPIO_pins = [16, 15, 17, 18, 19, 13, 12, 14]
out = [None] * 8
for n in range(8):
  out[n] = Pin(GPIO_pins[n], Pin.OUT)
print(out)

def Output(bits):
  for n in range(8):
    out[n].value((bits >> n) & 1)

#                        AGFEDCB.
def Off()    : Output(0b_00000000)
def Zero()   : Output(0b_10111110)
def One()    : Output(0b_00000110)
def Two()    : Output(0b_11011010)
def Three()  : Output(0b_11001110)
def Four()   : Output(0b_01100110)
def Five()   : Output(0b_11101100)
def Six()    : Output(0b_11111100)
def Seven()  : Output(0b_10000110)
def Eight()  : Output(0b_11111110)
def Nine()   : Output(0b_11101110)

counter = [Off(), Zero(), One(), Two(), Three(), Four(), Five(), Six(), Seven(), Eight(), Nine()]
counter(1)

Obviously this didn't work as the "list object isn't callable". How might I make the functions callable from a matrix?

Re: Make a counter

Posted: Fri Jun 11, 2021 12:42 pm
by fdufnews
You'd better try

Code: Select all

counter = [Off, Zero, One, Two, Three, Four, Five, Six, Seven, Eight, Nine]
counter[1]()

Re: Make a counter

Posted: Fri Jun 11, 2021 4:28 pm
by hippy
Or you can cut out the middle man of naming ...

Code: Select all

#             AGFEDCB.
counter = [0b_10111110, # 0
           0b_00000110, # 1 
           0b_11011010, # 2 
           0b_11001110, # 3 
           0b_01100110, # 4 
           0b_11101100, # 5 
           0b_11111100, # 6
           0b_10000110, # 7 
           0b_11111110, # 8 
           0b_11101110, # 9 
           0b_00000000] # 10 - Off

Output(counter[7])
You can of course move 'counter[]' into the 'Output' routine ...

Code: Select all

counter = ....

def Output(digit):
  bits = counter[digit]
  for n in range(8):
    out[n].value((bits >> n) & 1)
    
Output(7)