CREMA Firmware

Hey Everyone,

I know it’s been a bit since I’ve done an update but I wanted to put it out there – the first public revision of the CREMA firmware!! It’s being released under the Creative Commons Attribution-ShareAlike License so as to provide a significant amount of freedom with respect to what people can do with it.

You can get it here: https://github.com/josh-blake/CREMA

Presently, the CREMA firmware provides you with:

  • Custom brew Presets and the ability to modify: temperature, duration, and pump duty.
  • Real time clock with alarm and auto-on / off.
  • Steam temperature control with auto-refill (marching ants).

There is a LOT more that I need to do with the CREMA firmware including:

  • Storage / Retrieval of settings from Flash Memory
  • Modifying PID settings (they’re currently hard-coded)
  • Finishing off the rest of the menu elements

A note about compiling this firmware: you WILL need to enable SPRINTF functions with FLOAT capabilities as I’ve previously outlined (http://josh.to/crema/rebuilding-the-arduino-ide-to-support-sprintf-with-floats/). Everything else should work as is.

I’ll post the hardware next!

Cheers,

Josh.

10 thoughts on “CREMA Firmware

  1. Josh

    I’ve been following your blog closely.

    I think that what you have done, and taken the time to document, is superb, thanks for your hard work.

    I have got your code up and running on a breadboard circuit.

    For the display, I used an Adafruit LCD Shield Kit, which works on I2C ( http://www.adafruit.com/products/714). It’s probably not as robust as the crystalfontz one you are using, but it’s less than half the price. The Adafruit library made it pretty easy to convert the button code. The only problem is it has one less button than you are using (no “cancel”), so I’ll have to implement a cancel option to exit the menu.

    Secondly, I don’t want to leave my Silvia on all the time and have to set the clock, so I have connected up the RTC with a battery back-up, which worked fine.

    I would be really interested to see a schematic to explain how you changed the wiring for the solenoid valve, if possible.

    Keep up the good work, I appreciate it, and look forward to your next updates.

    Cheers

    Chris

    • Hey Chris!

      Glad to hear things are working out well for you in your attempts to hack about Miss Silvia!

      You can change the firmware relatively easily – especially for the menu – just by changing the menu jump points. I was trying a few different ‘navigation’ configurations when I designed the menu, and I found the prospect of using a left arrow to ‘back out’ of a menu and the right arrow to ‘advance forward’ trough a menu appealing. Rather than needing a cancel button, you could just have it so that a left arrow at the root menu exits the menu system. You can call the function void menuMode_P() and pass the desired run mode level to the function (in the case where it’s idling at temperature, it’s mode 2). If you’re not familiar how to do this with the current menu structure and implementation (I know it’s convoluted …. but it’s a necessity) I can elaborate more for you.

      Regarding the wiring diagram, I can get one up in a few days but it’s really quite simple. The Silvia wiring diagram is found on page 48 of this document: http://www.ranciliogroup-csdoc.com/User%20Manuals/MAN_Silvia(2012-04).pdf. I disconnected the Hot Water switch (IA) N wire and Brew Switch (IC) BL wire at their respective switches and wired them together using a Male-Male quick-connect splice. This frees up a tab on the brew switch that goes hot when the brew switch is thrown (wired up to the brew switch LINE sensor), and gives the solenoid valve coil a discharge path through the common (N) line.

      Hope that helps! Keep me posted!

      Cheers,

      Josh.

      EDITED: Male-Male quick-connect splice.

  2. Hi Josh

    Thanks for the advice.

    To change the menu to account for the fact of having no “cancel” button I followed your suggestion as follows:

    I changed:
    in // 0 Arguments
    //PROGMEM const void* const MA0_L[] = {(void*)8}; //comment out menu jump to menu item 8
    PROGMEM const void* const MA0_L[] = {(void*)2}; //points to menuMode 2

    in // 0 – Edit Presets
    //(void*)menuGoto_P, MA0_L, //left button – comment out menuGoto 8
    (void*)menuMode_P, MA0_L, //left button – menuMode function

    It works!

    I will use this, and add in any other places that I need to exit the menu.

    Regarding the wiring diagram, I’m double checking here, did you connect the two newly-loose wires (N & Bl) together, or the newly-free tabs on the switches (IA and IC) together? It’s the use of the term female-female splice that has confused me

    • Glad to hear that the menu was hackable for you :)

      I should have clarified that the Bl and N wires were connected together. Now that I think about it, it was a male-male splice… I believe that in the current Silvias, both Bl and N wires are black. Whatever you do, just don’t connect Black to White or Red (you’ll blow your circuit breaker in your house :) … )

  3. I have a further comment, I thought might be useful for anyone trying a different display. This is my first project with Arduino, so my apologies if this is really basic stuff.

    It regards the 100ms delay in void loop().

    At start of void loop():
    timeLoop = millis();

    functions – (that take time to run, so millis() increases)

    At end of void loop():
    delay(100 + timeLoop – millis()); //Iterate every 100ms to ensure PID retains accuracy

    This meant that when I first fired up the code, the display showed: “0.0°C 00:00a” on the first line, and was unresponsive to button presses.

    I find that the loop is taking longer than 100ms to run for me. This is probably because I am using a different LCD display (as noted in the first comment), and the code for checking button presses or writing to the display are slower.

    If the loop takes longer than 100ms, then the calculation creates a negative number (e.g. 100ms + 100ms – 201ms) = -1, which results in a very long delay and the loop effectively stops.

    I increased the delay to 250ms, which works, but it’s obviously not as frequent on running the PID code as the original code.

    Do you have any thoughts on this?

    Regards

    Chris

    • Hey Chris,

      It might be worthwhile editing the library for your display instead to speed up that code. Chances are it’s using some sort of code blocking to poll for keypresses (think something to do with the delay() function). What display library are you using?

      If you’d rather not edit the display library, a decreased refresh time shouldn’t be too much of a problem. You might have to retune the PID parameters though (they’re meant to be tuned :) anyways…). What you do want to do though is make sure that you’re looping at a fixed interval (this is necessary for the PID to remain well-defined). The loop can have a variable execution time depending on what the system is currently doing etc. so in order to make a fixed time interval, it simply delays for the remaining block of time in that interval. Hardware interrupts can still occur though (think switches being turned on or off, or an alarm event occurs) even while the system is delaying.

      Caveats with a slower interval mean that the screen might appear jittery, and response to your buttons, switches, etc. will be equally jittery. I found that with anything greater than 100ms, that this delay was noticeable.

      Let me know how this works for you!

        • Chris – I took a quick look at the library and it appears that most of the delays should be inconsequential. Out of curiosity, how have you implemented the library in the main loop?

          • Thanks – sorry, not had time for a week or so, and now you’re helping debug my code!

            Some examples of my variations to your code:

            to read buttons:
            /*
            LCD.getKP();
            if (LCD.KP[1]) {timeSleep = millis();}
            */
            uint8_t buttons = lcd.readButtons(); // buttons
            if (buttons) {timeSleep = millis();}

            case 0: //Deep Sleep
            //if (LCD.KP[1]) {mode = 2;}
            if (buttons) {mode = 2;}

            Typical key press check:
            //if (LCD.KP[1] & (KP_OK | KP_LEFT | KP_RIGHT)) {mode = 7;} //Check for User OK
            if (buttons & (BUTTON_LEFT | BUTTON_RIGHT | BUTTON_SELECT)) {mode = 7;} //Check for User OK

            Lcd formatting and printing:

            //Line 0
            sprintf((char*)&lcdBuffer[2], “%-16s”, lcdBuffer[0]); //Left Justify and Pad with Spaces for LCD
            //LCD.print(lcdBuffer[2], 16, 0, 0);
            lcd.setCursor(0,0);
            lcd.print(lcdBuffer[2]);

            //Line 1
            sprintf((char*)&lcdBuffer[3], “%-16s”, lcdBuffer[1]); //Left Justify and Pad with Spaces for LCD
            //sprintf((char*)&lcdBuffer[3], “%4.1fs” , float(looptimemax)); //Left Justify and Pad with Spaces for LCD
            //LCD.print(lcdBuffer[3], 16, 0, 1);
            lcd.setCursor(0,1);
            lcd.print(lcdBuffer[3]);

            delay(198 + timeLoop – millis()); // extended delay

            I have found a clue in the Adafruit forums – Polling of the keys is intentionally slow in order to debounce the buttons: https://www.adafruit.com/forums/viewtopic.php?f=22&t=31826&p=158978&hilit=rgblcd#p159017

            So, I think I need to test how slow, and see if that is the issue.

          • Hey Chris – I don’t see anything immediately obvious or glaring in your code – it looks like it should do the trick. Just out of curiosity, have you removed (or at least commented out) all references to the CrystalFontz library and all I2C calls to the CrystalFontz display (including in the setup() void, and #include statements)? The easiest way to know for sure is to remove the #include references for the CrystalFontz library all together and the compiler will throw a fit otherwise. I know for sure that system will hang up if there is a call to a non-addressed component on the I2C bus and I’m just wondering if that might be causing it. I don’t think that the debounce is causing the issue either – it simply reads the keypresses 5 times consecutively (we’re talking about 1-2ms or so tops).

            I mean perhaps it could be a cumulative effect of the setCursor() and print statements (print sends each character as a separate transaction on the I2C bus – this can surprisingly eat up a lot of time) – but I’m still not yet convinced.

            Let me know what you find!! And I’ll keep thinking about it!

            Cheers,

            Josh.

Leave a Reply