The Gaspresso Propeller Project
Ripping apart a coffee maker and converting it to Propane- and 12V operation, and
developing a hideous control system to mimic ‘bot personality (Douglas Adams-like)
SW
HW
EL
HMI
I have always liked to write code in a maximum readability and selfdocumenting style. Compact code priority
comes last. I would like anyone (well, almost) to be able to read and understand the code, in particular the top
level code. For drivers and interfaces where speed limits are pushed, there is less option for non-compact code.
Still, extensive commenting can compensate for this.
Software structure
Taking advantage of Propeller’s excellent (8 ‘cogs’) parallel processing capabilities, and the real-time nature of
this project, I decided to put the top level Main code in the default cog, and the data aquisition modules in
separate cogs where they run endlessy and update global variables accessible to the Main code. In this way
the Main code does not need to bother with reading values before acting, but can just pick the most recent (e.g.
pressure measurement) value from the relevant global variable. For other, once in a while kind of tasks, like
reading from the SD card reader, the software module will claim a new cog, execute, and then release the cog.
Objects
There are a number of sensor and device interfaces required. For these I have picked Object code from the
OBEX repository, and modified to tailor the object to my needs. I have also picked som conversion routine
library Objects from the same place, but for those I have cut away those routines not needed, in order to reduce
amount of total code.
Main code
Until now I have concentrated on getting driver and interface code up to speed, and testing the devices, so the
top level Main code is very much in the beginning. My approach is to first write the functionionality in sort of
meta code - as comments, and then step, by step write the real code, and test at each step.
{
Gaspresso Project Main.
Application (top level) code.
Controls the 'Gaspresso', a 'coffee-bot' inspired by stories by Douglas Adams. The main feature is its ability to give sarchastic or humourus
comments.
It also provides process control to the machine - which runs on propane and 12V DC, and brews espresso and a range of variants - even in a
location without power mains available.
Naming conventions:
Constants start with a capital, variables do not
By Erlend Fjøsna 2012
}
CON
_clkmode = xtal1 + pll16x 'Standard clock mode * crystal frequency = 80 MHz
_xinfreq = 5_000_000
'pin assignments:
LCD_PIN = 7 ' temporary assignment
PinPanic = 0
PinTrayPlace = 1
PinTrayWater = 2
PinPIRperson = 3
PinHit = 4
PinCup = 5
PinUnused = 6 '*
PinADCdata = 7 ' combined Pin for both din and dout
PinADCclk = 8
PinADCcs = 9
PinRTCclk = 10
PinRTCdata = 11 ' combined Pin for both din and dout
PinRTCce = 12
PinSDcs = 13
PinSDdi = 14
PinSDclk = 15
PinSDdo = 16
PinLCDdata = 17
PinIRclk = 18
PinIRdata = 19
PinENCa = 20
PinENCb = 21
PinVIBRATE = 22
PinUnused1 = 23 '*
PinSERVO = 24
PinAUDIOr = 25
PinAUDIOl = 26
PinPUMPirish = 27
PinUnused2 = 28 '*
PinPROP = 29
PinIMPUMP = 30
PinCOIL = 31
'ADC channels
ChLevelWater = 0
ChTempWater = 1
ChPressWater = 2
ChPositionHolder = 3
ChWeightCup = 4
ChVoltageSupply = 5
ChUnused1 = 6
ChUnused2 = 7
'moods
MoodPissed = 10
MoodAngry = 11
MoodHappy = 12
MoodUnhappy = 13
MoodFriendly = 14
MoodStressed = 15
MoodPuzzled = 16
MoodFormal = 17
MoodWiseguy = 18
MoodPolitical = 19
MoodMacho = 20
MoodLonging = 21
MoodAlternative = 22
MoodAdolescent = 23
MoodSlow = 24
MoodSleepy = 25
MoodServing = 26
MoodIndifferent = 27
MoodSharp = 28
MoodIronical = 29
MoodSayings = 30
MoodLatinuser = 31
MoodPoetic = 32
MoodRhyme = 33
MoodChuckle = 34
MoodAdvertising = 35
MoodSulking = 36
MoodTechno = 99
'messages
MsgTadaa = 999
'parameters
LCD_BAUD = 19_200
LCD_LINES = 4
MaxSelQuiet = 5 'Sec
MaxWaitAction = 30 'Sec
MaxMoods = 99
ValTempTeawater = 99 'deg C
ValTempCoffee = 92 'deg C
VAR
'Variables to hold I/O values
'============================
'ADC analogue input values
LONG adcLevelWater
LONG adcTempWater
LONG adcPressWater
LONG adcPositionHolder
LONG adcWeightCup
LONG adcVoltageSupply
LONG adcUnused1
LONG adcUnused2
'Analogue input values from comms
LONG aiTempGas
LONG aiPosEncoder
'Analogue, frequency or pwm = 'numeric output' values
LONG noServoGas
LONG noVibrate
LONG noFreqPump
'Variables to hold other global variables
'========================================
LONG valSelQuiet
LONG spTempWater
LONG spPressWater
LONG valEncoder
BYTE statusMachine
BYTE statusWakeup
BYTE binPanic
BYTE binInposTray
BYTE binFullTray
BYTE binPerson
BYTE binHit
BYTE binInposCup
BYTE bin
OBJ
SD : "FSRW" 'read/write to SD memory card
Wav : "SDwavPlay" 'play from defined range of wav files
Lcd : "Debug_Lcd" 'write text to LCD
Encoder : "Quad Decoder" 'reads quad encoder, user input
PUB Main
'Startup procedures
'==================
'-get the LCD going
lcd.init(LCD_PIN, LCD_BAUD, LCD_LINES)
lcd.cursor(0)
lcd.cls
lcd.backLight(true)
'-first greeting
lcd.str(string("Hello world...,", 13))
'-and play the ta'daa
'Wav.play(MsgTadaa, MoodTechno) 'change to current random mood - moodNow
lcd.str(string("Gaspresso greets", 13))
'-start the encoder reading
Encoder.start(PinENCa, @valEncoder)
repeat 10
lcd.dec(valEncoder)
waitcnt(clkfreq + cnt)
{
ReadGlobalsSD
Reads remembered values from SD card and assigns to global variables
Start CogADC
To continously read analogue inputs and assign to global variables
[Set global error status in case values are out of range]
Start CogRTC
To continously read time and date and assign to global variables
Start CogWavPlayer
Monitors global variables, if changed selects Comment and plays corresponding .wav file
MachineStatus
Checks voltages, levels, etc. to be healthy
Announces hardware status
Sets statusMachine
}
{
REPEAT main loop
REPEAT user input loop
Check User Input variables
User selection: aiPosEncoder(Rotary Encoder)
Hit detect: binHit(Piezo)
Person detect: binPerson (PIR)
Panic detect: binPanic (Panic button)
CASE User Input event
UserSelection
Set UserSelectionTime
Assign prelim User Selection
PlayWav choice
PrintLCD choice
Set WakeUp TRUE
HitDetect
PlayWav greeting(RND, Time, Date)
PrintLCD greeting
PersonDetect
PlayWav shout(RND)
PanicDetect
pick howPanic
Panic(howPanic)
ENDCASE
Calculate Selection Quiet: valSelQuiet
-time since last UserSelection event
UNTIL SelectionQuiet > MaxQuietUser AND WakeUp TRUE end user input loop
CASE UserSelection
Nothing
PlayWav stupid(RND)
Teawater
IF HolderIn
Tell(Remove holder)
IF CupOut
Tell(place cup under)
WAIT UNTIL (NOT HolderIn AND CupOut) OR Wait > MaxWaitForAction
WaterSetTemp := TeaWaterTemp
US coffee
Farmers coffee
Americano Long
AmericanoShort
Espresso Normal
Espresso RedEye
Turkish
Irish coffee
Irish
ENDCASE
}
PRI private_method_name
DAT
name byte "string_data"
so far
so good
Programming style
The software story