tisdag 8 oktober 2013

RaspyFi and Adafruit 16x2 Char LCD Plate

I just found out about the RaspyFi distribution for Raspberry Pi. From RaspyFi homepage:
RaspyFi is an open source linux distribution. It will transform your Raspberry Pi into anaudiophile source, in 10 minutes without hassles. It comes ready to play, and it’s compatible with almost every USB DAC available.
This was perfect for me because I had for some time been thinking of building some kind of "music station" that I could use together with my NuForce uDAC 2 and my Sennheiser HD598. I was thinking about using an old laptop but an Raspberry Pi is even better. Small, quiet, power efficient and just very cool.

After writing the image to an SD-card I was playing music within minutes and it worked great! I controlled the music from a web-browser and my Android phone which was ok but it made me start thinking about building some control functionality into the device itself. Then I realized was that I had the solution in one my electronics storage boxes! I had a Adafruit Blue&White 16x2 LCD+Keypad Kit for Raspberry Pi that I didn't had time to put together earlier.

After some soldering I had a nice display with five buttons on top of the Raspberry Pi. The soldering and software installation was very easy thanks to Adafruits excellent user-guide that can be found here.

The last piece of the puzzle was to display song information on the 16x2 LCD display and use the keypad to control the playback. First I was inspired by this thread in the RaspyFi forums, they used lcdproc and mpdlcd but I didn't find drivers for the Adafruit LCD and I didn't feel like writing my own drivers (maybe its not that hard?).

Instead of using something "ready" I decided to make my own "driver" based on a simple python script using Adafruits python library for communicating with the display and the command line program mpc for communicating with mpd.

The software features:
  • Presentation of play mode (playing/paused/stopped), Artist and Song name scrolling on line 1
  • The elapsed song time, total song time and percentage of song played on line 2.
  • Left button: Skip back
  • Right button: Skip forward
  • Up button: Play
  • Down button: Stop
  • Select button: Toggle Play/Pause


Here is the code (showSongInfo.py):

#!/usr/bin/python
# Todo
# * display brightness timout, i.e. turn off display when stopped or paused for a while
#
import subprocess
import textwrap
from time import sleep
from Adafruit_CharLCDPlate import Adafruit_CharLCDPlate

class TextScroller:
	'Class for scrolling text'
	text = ''
	position = 0
	textLength = 0

	def __init__(self, initialText, textLength):
		self.text = initialText
		self.textLength = textLength

	def scroll(self):
		doubleText = self.text + '     ' + self.text
		scrolledText = doubleText[self.position:len(doubleText)]		
		self.position = self.position + 1
		
		# We add five extra spaces between each complete text scroll.
		if self.position > len(self.text) + 4 :
			self.position = 0		

		return scrolledText

	def setNewText(self, newText):
		self.text = newText
		self.position = 0

# Initialize the LCD plate.  Should auto-detect correct I2C bus.  If not,
# pass '0' for early 256 MB Model B boards or '1' for all later versions
lcd = Adafruit_CharLCDPlate()
lcd.begin(16,2)

# Clear display and turn on backlight
lcd.clear()
lcd.backlight(lcd.ON)

# Poll buttons
btn = (lcd.LEFT, lcd.UP, lcd.DOWN, lcd.RIGHT, lcd.SELECT)

lastArtistSong = ''
scroller = TextScroller('', 16)

while True:
	# Get current status and playtime
	process = subprocess.Popen('mpc', shell=True, stdout=subprocess.PIPE)
	status = process.communicate()[0]
	statusLines = status.split('\n')
	
	# Check if mpc returns more that one line plus an extra, in that case we dont have stopped the music and can parse additional information
	if len(statusLines) > 2:		
		# Extract the songName (first line)
		songName = statusLines[0]

		# Extract play status
		playStatus = statusLines[1].split(' ',1)[0].strip()

		# Extract a string like '2:01/3:43 (54%)' from the string '[playing] #2/13   2:01/3:43 (54%)'
		time = statusLines[1].split('   ',1)[1].strip()
	else:
		songName = ''
		playStatus = '[stopped]'
		time = '0:00/0:00 (0%)'

	lcd.setCursor(0,0)
	# Without scolling of text
	#lcd.message((playStatus + ' ' + songName)[0:16] + '\n' + (time + '     ')[0:16])
	
	# with scolling text
	artistSong = (playStatus + ' ' + songName)
	if artistSong != lastArtistSong:
		scroller.setNewText(artistSong)
		lastArtistSong = artistSong

	if songName != '':		
		lcd.message(scroller.scroll()[0:16] + '\n' + (time + '     ')[0:16])
	else: 
		lcd.message((playStatus + '             ')[0:16] + '\n' + (time + '     ')[0:16])
	
	# Poll the buttons most of the sleep time, to make them responsive the plan is to 
	# poll the buttons for 400ms and then update the status on the display
	# If we sleep for 40ms between each poll time and have five buttons that equals to 200 ms
	# Two iterations of this gives us 400 ms.
#	for i in range (0, 10):
	for i in range (0, 5):
	   for b in btn:
	        if lcd.buttonPressed(b):
			if b is lcd.RIGHT:
				subprocess.Popen('mpc next', shell=True)
				sleep(0.2) # Sleep a little extra to avoid dubble registrations
			if b is lcd.LEFT:
				subprocess.Popen('mpc prev', shell=True)
				sleep(0.2) # Sleep a little extra to avoid dubble registrations
			if b is lcd.UP:
				subprocess.Popen('mpc play', shell=True)
				sleep(0.2) # Sleep a little extra to avoid dubble registrations
			if b is lcd.DOWN:
				subprocess.Popen('mpc stop', shell=True)
				sleep(0.2) # Sleep a little extra to avoid dubble registrations
			if b is lcd.SELECT:
				subprocess.Popen('mpc toggle', shell=True)
				sleep(0.2) # Sleep a little extra to avoid dubble registrations
		        break
  	   sleep(0.04)  
 


I autostart the python script by adding the following line to the root crontab (sudo crontab -e):
@reboot sudo python /home/pi/Adafruit-Raspberry-Pi-Python-Code/Adafruit_CharLCDPlate/showSongInfo.py



Video of the display in action.

Part list

  • Raspberry Pi
  • 5V power supply
  • 16 GB SD-card
  • Adafruit 16x2 LCD Plate
  • NuForce uDAC 2
  • Network Cable
  • Sennheiser HD598
  • Case (e.g. Adafruit Pi Box or similar)

Todo

That is left to do is to assemble my PiSupply kit and connect to the wireless network using an USB WIFI dongle and maybe mount all parts in some clever way.


onsdag 3 april 2013

Utvärdering av jordfuktighetssensor

Denna sensor kommer bland annat användas i växthusövervakningsprojektet men även i trådlösa sensornoder i rabatter och pallkragar.

Jordfuktighetssensor kopplad till Arduino Uno

Sensorn har fyra anslutningar, VCC, GND, D0 och A0. D0 är en digital utgång som går hög när fuktigheten kommer över en viss gräns (ställs med en vridpot på sensormodulen). A0 är en analog utgång som skalas mellan GND och VCC proportionellt mot fuktigheten i jorden.

Vid ett test med en relativt fuktig växt drar sensorn 7.4 mA@5V och 4.2 mA@3.3V. Det innebär att sensorn lämpar sig väl för trådlösa sensornoder som vaknar t.ex. var tionde minut och tar en snabb (kanske 10 ms lång) fuktighetsavläsning som skickas via radio till en datainsamlingsnod.

onsdag 27 mars 2013

Strömförbrukning ATtiny85, MSP430 och ATtiny84A

Tanken med ATtiny85 kretsen är att använda den i små sensornoder som drivs med batteri. Därför är det viktigt att strömförbrukningen är så låg som möjligt. En typ av sensornod är en trådlös temperatursensor baserat på en DS18B20 samt en 433 MHz radiosändarmodul. Denna typ av nod kan vara i stand-by läge den mesta delen av tiden och bara vakna t.ex. var femte minut för att göra en temperaturavläsning som skickas via radio. Sedan kan noden gå ned i stand-by läge igen för att spara ström.

För att testa detta skapades ett litet testprogram som sätter MCUn i sleep_mode_pwr_down äge och som sedan väcks av WDT var åttonde sekund. När noden väckts tänds en led i en sekund och så går noden ner i power down läge.

För att mäta strömförbrukningen kopplade jag en multimeter inställd på strömmätning i serie med strömkällan (ett 3.7V, 2400 mAh, 18650 batteri, vilket var laddat till 4.13V).

Strömförbrukning i vaket tillstånd med LED tänd: 4.64 mA
Strömförburkning i vaket tillstånd med LED urkopplad: 1.073 mA
Strömförbrukning sleep_mode_pwr_down: 6 uA

Vissa sensorer kan kräva 5V spänningsmating. I dessa fall kan en step-up modul användas. För att se hur den påverkar strömförbrukningen gjordes samma experiment med en krets som tar 3.7 V från batteriet som input och lämnar ut 5V.

Strömförbrukning i vaket tillstånd med LED tänd: 11 mA
Strömförburkning i vaket tillstånd med LED urkopplad: 2.4 mA
Strömförbrukning sleep_mode_pwr_down: 0.3 mA = 300 uA

En stooor försämring!

Som sista experiment slogs BOD (Brown Out Detection) av vid power_down, det gjorde följande med strömförbrukningen:



Strömförbrukning i sleep_mode_pwr_down: 4-5 uA.

Med en strömförbrukning på 4 uA den mesta delen av tiden borde ett batteri kunna räcka rätt länge. För att veta exakt kan man använda kalkylatorn på: http://oregonembedded.com/batterycalc.htm

Om man i batterikalkylatorn använder ovanstående värden tillsammans med 18650 batteriet (2400 mAh) och väcker MCUn under en sekund 12 ggr i timmen skulle batterierna räcka i 5.39 år!

Test med 3.21V matning (2 x AAA).
Strömförbrukning i vaket tillstånd med LED tänd: 1.503 mA
Strömförburkning i vaket tillstånd med LED urkopplad: 0.748 mA
Strömförbrukning sleep_mode_pwr_down: 3 uA

Test med 3.3V matning.
Strömförbrukning i vaket tillstånd med LED tänd: 1.876 mA
Strömförburkning i vaket tillstånd med LED urkopplad: 0.804 mA
Strömförbrukning sleep_mode_pwr_down: 4 uA


Test med 5V matning.
Strömförbrukning i vaket tillstånd med LED tänd: 6.45  mA
Strömförburkning i vaket tillstånd med LED urkopplad: 1.293 mA
Strömförbrukning sleep_mode_pwr_down: 5 uA

Nästa steg blir att göra samma test med en TI MSP430-G2553 och se hur den står sig med ATtiny85. Kommer även att utvärdera ATtiny84A med ATMELs picopower teknologi.

Uppdattering: MSP430-G2553 med 3.3V störmförsöjning från en Arduino Uno
Strömförbrukning i vaket tillstånd med LED tänd: 1.57 mA
Strömförbrukning i sovande tillstånd med LED tänd: 1.29 mA
Strömförburkning i vaket tillstånd med LED urkopplad: 355 uA
Strömförbrukning LPM3 (Timerinterupt): 1 uA (minsta värde multimetern kan mäta)

Om man i batterikalkylatorn använder dessa värden tillsammans med två AA batterier (1200 mAh) och väcker MCUn under en sekund 12 ggr i timmen skulle batterierna räcka i 10.44 år!

Med två AAA batterier på 3.21 V

Strömförbrukning i vaket tillstånd med LED tänd: 1.411 mA
Strömförbrukning i sovande tillstånd med LED tänd: 1.144 mA
Strömförburkning i vaket tillstånd med LED urkopplad: 345 uA
Strömförbrukning LPM3 (Timerinterupt): 1 uA (minsta värde multimetern kan mäta)

Det verkar som om MSP430 verkligen rockar när det gäller low power! Ska bli kul att se om ATMELs picopower kan rå på TI:s MSP430.

Både 5.39 och 10.44 år är väldigt mycket och det finns anledning att tro att batteriernas självurladdning är det som påverkar tiden mest.

ATtiny84A

För att mäta strömförbrukningen kopplade jag en multimeter inställd på strömmätning i serie med strömkällan (ett 3.7V, 2400 mAh, 18650 batteri, vilket var laddat till 4.13V).
Strömförbrukning i vaket tillstånd med LED tänd: 4.18 mA
Strömförburkning i vaket tillstånd med LED urkopplad: 717 uA
Strömförbrukning sleep_mode_pwr_down: 4 uA


Med två AAA batterier på 3.21 V

Strömförbrukning i vaket tillstånd med LED tänd: 1.5 mA
Strömförburkning i vaket tillstånd med LED urkopplad: 500 uA
Strömförbrukning sleep_mode_pwr_down: 4 uA

Med sleep bod disabled och två AAA batterier:

Strömförbrukning sleep_mode_pwr_down: 3 uA

Sammanfattning

Det verkar som om Atmels picopower inte riktigt rår på TI:s MSP430 serie. Även om ATtiny drar 3 gånger så mycket som MSP430 i standby så är de väldigt strömsnåla. Dock är MSP430 king of low power.


Programmera ATtiny85 och ATtiny84A med AVR Dragon

Detta är en guide till hur man programmerar en ATtiny85 och ATtiny84A med hjälp av en AVR Dragon programmerare och AVR Studio 5.1.

ATtiny85

Jag kommer använda ISP (In System Programming) metoden (som nyttjar SPI protokollet). För att se hur man skall koppla in draken går man lämpligtvis till denna länk. Där finns följande bild.
SPI programming and debugWIRE debugging

Detta är egentligen allt som behövs. Jag kopplade upp ovanstående på en breadboard med jumper wires.
Inkoppling av AVR Dragon för att programmera ATtiny85. Vid programmeringsläge ansluts tinyn till pin 10-13 på breadboard.
När inkopplingen är gjort är det mycket viktigt att ställa hastigheten i programmeringshanteraren i AVR Studio till 125 kHz. Om man försöker med defaultvärdet på 1 MHz funkar det inte alls.

ATtiny84A

Jag kommer använda ISP (In System Programming) metoden även för ATtiny84A:an. För att se hur man skall koppla in draken går man lämpligtvis till denna länk:

Där finns följande bild: 

VCC

6
B
nc
5
4
G
nc
3
2
nc
nc
1

HV_PROG

20
nc
nc
19
18
nc
nc
17
16
nc
nc
15
14
nc
nc
13
12
nc
nc
11
10
nc
nc
9
8
nc
nc
7
6
nc
nc
5
4
nc
nc
3
2
nc
nc
1

ISP

6
F
E
5
4
D
C
3
2
B
A
1

JTAG

10
nc
nc
9
8
nc
nc
7
6
nc
nc
5
4
nc
nc
3
2
nc
nc
1

DEVICE


nc
nc


nc
nc


nc
nc


nc
nc


nc
nc


nc
nc


nc
nc


nc
nc


nc
nc


nc
nc


nc
nc


nc
nc


nc
nc

8
A
D
7
9
C
nc
6
10
nc
nc
5
11
nc
E
4
12
nc
nc
3
13
nc
nc
2
14
F
G
1

söndag 17 mars 2013

Rainbow Cylon project

Detta projektet går ut på att undersöka hur RGB-LEDar fungerar och hur man driver/styr dem. För att göra detta kommer effekten i ögonen hos robot-versionen av Cylons i Battlestar Galactica simuleras (ser ut som Kitt från Knight Riders röda lampor i fram). Förutom att använda färgen röd kommer även alla regnbågens färger användas.

Material
Arduino Uno
10 st RGB LEDs (Länk)
2 st TLC5940 drivkretsar, seriell ingång och 16 PWM utångar (Länk).
Breadboard
Kablar

Progress:
Har kopplat in en TLC5940 och driver den röda dioden i 10 stycken RGB-leds. Kör Cylon-svepet.
Skulle ladda upp en video men det verkar inte funka. :(

Nästa steg blir att koppla in alla tre led:arna och de andra TLC5940 kretsen. Då kommer 30 av de 32 PWM-kanalerna behöva användas. Många (10x4) jumpercables blir det...


lördag 16 mars 2013

Nattlampa med Colorduino

Detta projekt går ut på att bygga en nattlampa som visar solens och månens upp och nedgång på de tider som dottern bör sova. Det innebär att när det är läggdags går solen ner och månen kommer fram. När det är dags att gå upp går månen ner och solen upp. På så sätt vet hon när det är dags att gå upp (hindrar säkert inte henne från att gå upp och leka mitt i natten men ändå).

Basen i projektet är en Colorduino med en 8x8 RGB LED matris. En Colorduino är en Arduino-kompatibel enhet med en Atmel Atmega328, LED drivkretsar (24 st PWM ut) samt Darlingtontransitorer för att strömförsörja alla LEDar. Själva matrisen är av typen "common anode", dvs den har totalt 32 pinnar, 8 st common anode och sedan 8 stycken för respektive färg (Röd, Grön, Blå).

Tanken är att göra ett antal "bilder/animationer":
* Solen går upp och månen ned, snygga röda färger för att simulera soluppgång.
* Solen går ned och månen upp, samma som ovan med åt andra hållet.
* Månen är uppe på en stjärnhimmel med blinkande stjärnor.
* Solen är uppe, kanske vandrar den över himlen beroende på tid på dagen.

Enheten konfigureras med de tider som gäller på veckodagarna respektive helgen. T.ex. på veckodagar går solen upp klockan 07.00 och ned 19.00. På helgerna går solen kanske inte upp förrän 08.30 men ned 19.00.

Hela matrisen byggs sedan in i en lämplig fotoram för att vara snygg att se på.

Material
Colorduino (Länk)
8x8 RGB LED matrix (Länk)

Progress:
Nu har sakerna kommit och en första programmering är gjort med hjälp av en FTDI-adapter och Arduino-utvecklingsmiljön.

lördag 9 mars 2013

Detaljerad loggning av elförbrukning

I dagsläget använder jag 1-wire räknare för att logga elförbrukningen från tre olika elmätare (huvudmätare, bergvärmepump och FTX-system). 1-wire räknarna läses av varannan minut och data sparas i en databas. Detta fungerar bra för att se total förbrukning per dygn eller månad men dåligt för att se momentan förbrukning. I dagsläget blir de momentana förbrukningen samma som medelförbrukningen under två minuter vilket inte är tillräckligt för att kunna se individuella förbrukare.

Tanken är att utöka systemet med en Arduino Uno med Ethernet-shield som räknar pulser från huvudmätare och bergvärmemätare och sedan skickar dessa till en port på en server där en applikation tar emot datan och lagrar i en databas.

Progress:
* Ethernet-shielden är testad genom ett program som läser av en 1-wire temperatursensor och sedan skickar temperaturen till en socket på en PC.