I've made an Internet Radio using a Raspbbery Pi, Rotary encoder,
and 20x4 LCD. Stations are selected with a rotary encoder, and the
switch is pressed to play the stream.
Each stream is decoded with linux mpc and any track/artist data sent
to the display.
It all works ecept as I turn the switch I encounter "jitter". The
count is diaplay on last line of 4 line display and if I rotate
too quickly digits are missed and turning anticlockwise is even
more erratic, sometimes skipping numbers altogether.
There may not be anything wrong with the code, the Raspberry Pi is the
fisrt Model B single core at 700MHz and it may just be too resource
hungry.
The tutorial for the Rspberry Pi is below:
https://www.modmypi.com/blog/how-to-use-...spberry-pi
I modified the code to use the switch on the rotary encoder, attached as
rotary_mod.py below:
The functions lcd-init(), lcd_cls(), lcd_string() etc are from the
lcd_module , listing below:
but any ideas about the switch jitter are welcome.
Again its possible that the Pi is a little underpowered to handle
the data stream, update display and respond to rotary switch at the same
time.
Thanks in advance.
and 20x4 LCD. Stations are selected with a rotary encoder, and the
switch is pressed to play the stream.
Each stream is decoded with linux mpc and any track/artist data sent
to the display.
It all works ecept as I turn the switch I encounter "jitter". The
count is diaplay on last line of 4 line display and if I rotate
too quickly digits are missed and turning anticlockwise is even
more erratic, sometimes skipping numbers altogether.
There may not be anything wrong with the code, the Raspberry Pi is the
fisrt Model B single core at 700MHz and it may just be too resource
hungry.
The tutorial for the Rspberry Pi is below:
https://www.modmypi.com/blog/how-to-use-...spberry-pi
I modified the code to use the switch on the rotary encoder, attached as
rotary_mod.py below:
rom RPi import GPIO from time import sleep clk = 22 dt = 27 sw = 17 GPIO.setmode(GPIO.BCM) GPIO.setwarnings(False) GPIO.setup(clk, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) GPIO.setup(dt, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) GPIO.setup(sw, GPIO.IN, pull_up_down=GPIO.PUD_UP) counter = 0 clkLastState = GPIO.input(clk) def function(): clkState = GPIO.input(clk) dtState = GPIO.input(dt) switch = GPIO.input(sw) global clkLastState,counter if clkState != clkLastState: if dtState != clkState: counter -= 1 else: counter += 1 clkLastState = clkState sleep(0.01) if counter == 20: counter = 0 return(counter,switch) # return count pstn and switch on or offThe Radio program I have called test.py for now:
from RPi import GPIO from time import sleep import lcd_module from lcd_module import * import subprocess import rotary_mod lcd_init() lcd_bl(1) lcd_cls() tk ="" def decode(): track = subprocess.getoutput('mpc current') if track == "": return track = track.split(':')[-1] art = track.split('-')[0] tk = track.split(' -')[1:] print(tk) tk = ",".join(str(x) for x in tk) print (tk) #tk = (track.lstrip(' ')).split(' -')[1:] #tk = str(tk.replace(',' , '')) print(art,tk) lcd_string(art, line2) if len(str(tk)) > 20: scroll(tk,line3) else: lcd_string(tk, line3) while True: # function() in rotary_mod returns (a,b) where a=count, b= sw state counter=rotary_mod.function()[0] switch=rotary_mod.function()[1] #print (counter) lcd_string(str(counter), line4) if (counter == 0): lcd_string1(" Push to clear LCD",line1) if (counter == 0 and switch == 0): lcd_cls() if counter == 1: lcd_string1(" Cinemix",line1) if (counter == 1 and switch == 0): lcd_cls() subprocess.call('mpc play 1', shell=True) station = "Cinemix France" lcd_string(station) decode() if counter == 2: lcd_string1(" Smooth Jazz",line1) if (counter == 2 and switch == 0): lcd_cls() subprocess.call('mpc play 2', shell=True) station = "Smooth Jazz" lcd_string(station) decode() if counter == 9: lcd_string( "Stop Music", line1) if (counter == 9 and switch == 0): subprocess.call('mpc stop', shell=True) lcd_cls()For clarity just two stations are selected from mpc playlist.
The functions lcd-init(), lcd_cls(), lcd_string() etc are from the
lcd_module , listing below:
import RPi.GPIO as GPIO import time # LCD to GPIO Mapping BCM numbering (Pin names after #) LCD_RS = 7 # CE1 LCD_E = 8 # CE0 LCD_D4 = 25 # P6 LCD_D5 = 24 # P5 LCD_D6 = 23 # P4 LCD_D7 = 4 # P1 # Backlight Control Pin (via BJT to control BL) LCD_BL = 18 # P7 # Display Characteristics # Set LCD width 16 or 20 characters per line LCD_WIDTH = 20 #LCD_CHR = True #LCD_CMD = False # Line address in RAM, if using 16x2 comment out line 3 and 4 line1 = 0x80 line2 = 0xC0 line3 = 0x94 line4 = 0xD4 line45 = 0xDe # LCD character true, lcd command set false LCD_CHR = True LCD_CMD = False # Timing constants for OLED displays check data sheet E_PULSE = 0.0005 E_DELAY = 0.0005 # Initialise GPIO ports def lcd_init(): GPIO.setwarnings(False) GPIO.setmode(GPIO.BCM) # Use BCM GPIO numbers GPIO.setup(LCD_E, GPIO.OUT) # E GPIO.setup(LCD_RS, GPIO.OUT) # RS GPIO.setup(LCD_D4, GPIO.OUT) # DB4 GPIO.setup(LCD_D5, GPIO.OUT) # DB5 GPIO.setup(LCD_D6, GPIO.OUT) # DB6 GPIO.setup(LCD_D7, GPIO.OUT) # DB7 GPIO.setup(LCD_BL, GPIO.OUT) # BL Gnd # Initialise LCD display parameters lcd_byte(0x33,LCD_CMD) # 110011 Initialise lcd_byte(0x32,LCD_CMD) # 110010 Initialise lcd_byte(0x06,LCD_CMD) # 000110 Cursor move direction lcd_byte(0x0C,LCD_CMD) # 001100 Display On,Cursor Off, Blink Off lcd_byte(0x28,LCD_CMD) # 101000 Data length, number of lines, font size lcd_byte(0x01,LCD_CMD) # 000001 Clear display time.sleep(E_DELAY) #################### Display Functions ############################## def lcd_byte(bits, mode): # Send byte to data pins, bits = data # mode = True for character, False for command GPIO.setwarnings(False) GPIO.setmode(GPIO.BCM) GPIO.setup(LCD_RS, GPIO.OUT) #new GPIO.setup(LCD_BL, GPIO.OUT) GPIO.output(LCD_RS, mode) # RS # High bits GPIO.output(LCD_D4, bits&0x10==0x10) GPIO.output(LCD_D5, bits&0x20==0x20) GPIO.output(LCD_D6, bits&0x40==0x40) GPIO.output(LCD_D7, bits&0x80==0x80) lcd_toggle_enable() # Low bits GPIO.output(LCD_D4, bits&0x01==0x01) GPIO.output(LCD_D5, bits&0x02==0x02) GPIO.output(LCD_D6, bits&0x04==0x04) GPIO.output(LCD_D7, bits&0x08==0x08) lcd_toggle_enable() def lcd_toggle_enable(): # Enable Display by toggling Pin 8 time.sleep(E_DELAY) GPIO.output(LCD_E, True) time.sleep(E_PULSE) GPIO.output(LCD_E, False) time.sleep(E_DELAY) def lcd_string1(message, line=line1): # Send string to display, defaults to line1 message = message.ljust(LCD_WIDTH) lcd_byte(line, LCD_CMD) # print at line number set by line for i in range(LCD_WIDTH): lcd_byte(ord(message[i]),LCD_CHR) # convert each char to hex and def lcd_string(message, line=line1): # Send string to display, defaults to line1 message = message.ljust(LCD_WIDTH) lcd_byte(line, LCD_CMD) # print at line number set by line for i in range(LCD_WIDTH): if (ord(message[i])) == 233: # check utf e grave lcd_byte(0,LCD_CHR) #replace custom charset 0 continue lcd_byte(ord(message[i]),LCD_CHR) # convert each char to hex and def scroll(scrollmsg, line=line1): # defaults to speed=0.4 and line1 takes 1 to 3 arguments scrollmsg = (" "+scrollmsg+" ") # Add space to message for i in range (len(scrollmsg)): #for i in range (16): lcd_string(scrollmsg[(LCD_WIDTH-i):i],line) #reverse needs padding with spaces time.sleep(s) def lcd_cls(): # clear all lines of display lcd_byte(0x01,LCD_CMD) def lcd_clr(line): # Clear line 1 or 2 by writing spaces lcd_string(" ",line) def lcd_bl(control): GPIO.output(LCD_BL, control)I realise that this is not possible to try unless someone has same hardware,
but any ideas about the switch jitter are welcome.
Again its possible that the Pi is a little underpowered to handle
the data stream, update display and respond to rotary switch at the same
time.
Thanks in advance.