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