Last active
March 14, 2016 22:12
-
-
Save nagubal/2065722 to your computer and use it in GitHub Desktop.
The file that is currently on an Arduino Uno with a serial number of 64935343333351F04132
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| enum DisplayMode { | |
| CLOCK_MODE = 0, // display clock only | |
| TEMPERATURE_MODE = 1, // display temperature only | |
| CLOCK_TEMP_MODE = 2, // display clock and temperature every 25 seconds for 5 seconds | |
| SET_CLOCK_MODE = 3 | |
| }; | |
| enum SettingsMode { | |
| SETTINGS_OFF = 0, | |
| SET_HOURS_MODE = 1, | |
| SET_MINUTES_MODE = 2, | |
| SET_SECONDS_MODE = 3 | |
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * The DATA_IN pin | |
| */ | |
| #define DATA_PIN 8 | |
| /** | |
| * The DIMM_IN pin should be pulled to LOW to enable display, | |
| * also used for brightness with PWM (using analogWrite()) | |
| */ | |
| #define DIMM_PIN 9 | |
| //11 | |
| /** | |
| * The CLK_IN pin | |
| */ | |
| #define CLK_PIN 10 | |
| /** | |
| * DS18B20 data wire is plugged into port 7 on the Arduino | |
| */ | |
| #define ONE_WIRE_BUS 7 | |
| #define ENC_PORT3 3 | |
| #define ENC_PORT6 6 | |
| /** | |
| * DS18B20 Power pin is connected on pin A3 | |
| */ | |
| #define ONE_WIRE_POWER A3 | |
| /** | |
| * Brightness potientiometer pin is connected on pin A1 | |
| */ | |
| #define BRIGHTNESS_POT_PIN A1 | |
| #define SQW_INTERRUPT_PIN 2 | |
| #define PIN_CLOCK_ONLY 4 | |
| #define PIN_TEMP_ONLY 5 | |
| #define PB4 4 //D12 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * USE_GITHUB_USERNAME=nagubal | |
| * | |
| * 2.3" 4 digits 7-segment clock, using the DE-DP003 from Sure Electronics | |
| * http://www.sure-electronics.net/mcu,display/DE-DP003.pdf | |
| * | |
| * The DE-DP003 is a common anode 7-segment LED display. | |
| * The LED driver chips are composed of 4pcs of 74HC595 and 5pcs of ULN2003. | |
| * Data should be clocked in from CLK_IN and DATA_IN in J1, and DIMM_IN pin should be pull to low to enable display. | |
| * PWM signal can be applied on the DIMM_IN pin to control brightness. | |
| */ | |
| #include <EEPROM.h> | |
| #include <Streaming.h> | |
| #include <Wire.h> | |
| #define ENCODER_USE_INTERRUPTS 1 | |
| // http://www.pjrc.com/teensy/td_libs_Encoder.html | |
| #include "Encoder.h" | |
| //https://github.com/akafugu/ds_rtc_lib | |
| #include <WireRtcLib.h> | |
| // http://www.pjrc.com/teensy/td_libs_OneWire.html | |
| #include <OneWire.h> | |
| // http://www.milesburton.com/?title=Dallas_Temperature_Control_Library | |
| #include "DallasTemperature.h" | |
| #include "pinConstants.h" | |
| // the DisplayMode enum declaration | |
| #include "displayMode.h" | |
| /** | |
| * La résolution du DS18B20; http://datasheets.maxim-ic.com/en/ds/DS18B20.pdf | |
| */ | |
| #define DS18B20_RESOLUTION 11 | |
| /** | |
| * the debounce time, increase if the output flickers | |
| */ | |
| #define DEBOUNCE 5 | |
| /** | |
| * Default brightness | |
| */ | |
| #define DEFAULT_BRIGHTNESS 7 | |
| #define CHRONODOT_ID 0x68 | |
| /** | |
| * The current display mode | |
| */ | |
| DisplayMode displayMode = CLOCK_TEMP_MODE; | |
| SettingsMode settingsMode = SETTINGS_OFF; | |
| WireRtcLib::tm* settingsTime; | |
| /** | |
| * segments to be switched on for digits on 7-segments display | |
| */ | |
| byte segments[] = { | |
| B11111100, | |
| B01100000, | |
| B11011010, | |
| B11110010, | |
| B01100110, | |
| B10110110, | |
| B10111110, | |
| B11100000, | |
| B11111110, | |
| B11110110 | |
| }; | |
| static unsigned int brightness_pwm; | |
| static unsigned int previousBrightness; | |
| boolean brightnessHasChanged = false; | |
| /** | |
| * used by the 1Hz interrupt | |
| */ | |
| volatile boolean displayNow = false; | |
| /** | |
| * the prevEncoderButton encoderButton from the input pin | |
| */ | |
| static uint8_t prevEncoderButton = 16; | |
| unsigned long millisEncButton = 0; // the last time the output pin was toggled | |
| // Change these two numbers to the pins connected to your encoder. | |
| // Best Performance: both pins have interrupt capability | |
| // Good Performance: only the first pin has interrupt capability | |
| // Low Performance: neither pin has interrupt capability | |
| Encoder myEnc(ENC_PORT3, ENC_PORT6); | |
| long oldPosition = -999; | |
| /** | |
| * RTC based on the DS1307/DS3231SN chip connected via I2C and the Wire library | |
| */ | |
| WireRtcLib rtc; | |
| /** | |
| * Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs) | |
| */ | |
| OneWire oneWire(ONE_WIRE_BUS); | |
| /** | |
| * Pass our oneWire reference to Dallas Temperature. | |
| */ | |
| DallasTemperature sensors(&oneWire); | |
| void setup() { | |
| brightness_pwm = DEFAULT_BRIGHTNESS; | |
| previousBrightness = DEFAULT_BRIGHTNESS; | |
| pinMode(DATA_PIN, OUTPUT); | |
| pinMode(CLK_PIN, OUTPUT); | |
| pinMode(DIMM_PIN, OUTPUT); | |
| digitalWrite(CLK_PIN, LOW); | |
| clearDisplay(); | |
| // handles the push button on the rotary encoder | |
| DDRB &= ~(1 << PB4); // set PB4 as an input | |
| PORTB = (1 << PB4); // Turn on the internal pull-up resistor for PB4 | |
| // set PIN_TEMP_ONLY & PIN_CLOCK_ONLY & SQW_INTERRUPT_PIN as an input | |
| //DDRD &= ~( (1 << PIN_TEMP_ONLY) | (1 << PIN_CLOCK_ONLY) | (1 << SQW_INTERRUPT_PIN) ); | |
| DDRD = DDRD | B00000000; | |
| //pinMode(PIN_TEMP_ONLY,INPUT); | |
| //pinMode(PIN_CLOCK_ONLY,INPUT); | |
| //pinMode(SQW_INTERRUPT_PIN,INPUT); | |
| // Turn on the internal pull-up resistor for PIN_CLOCK_ONLY & PIN_TEMP_ONLY & SQW_INTERRUPT_PIN | |
| //PORTD = ((1 << PIN_CLOCK_ONLY) | (1 << PIN_TEMP_ONLY) | (1 << SQW_INTERRUPT_PIN)); | |
| PORTD = PORTD | B00110100; | |
| // gestion du potentiomètre de luminosité | |
| pinMode(BRIGHTNESS_POT_PIN, INPUT); | |
| Serial.begin(57600); | |
| // set power pin for DS18B20 to output | |
| pinMode(ONE_WIRE_POWER, OUTPUT); | |
| //DDRC |= (1 << ONE_WIRE_POWER); | |
| // Initialisation du DS1307 | |
| Wire.begin(); | |
| rtc.begin(); | |
| sensors.begin(); | |
| if(sensors.getDeviceCount() > 0) { | |
| sensors.setResolution(DS18B20_RESOLUTION); | |
| } | |
| // enable SQW, 1Hz | |
| enableSQW(); | |
| // register interrupt function to 1Hz line | |
| attachInterrupt(SQW_INTERRUPT_PIN - 2, oneHzInterruptHandler, FALLING); // 1 = digital pin 3, 0 = digital pin 2 | |
| WireRtcLib::tm* now = rtc.getTime(); | |
| //Serial << "date: " << now->wday << " " << now->mday << "/" << now->mon << "/" << now->year << endl; | |
| Serial << "arduino up and running..." << endl; | |
| } | |
| byte enableSQW(void) { | |
| Wire.beginTransmission(CHRONODOT_ID); | |
| Wire.write(0x0E); // control register | |
| Wire.endTransmission(); | |
| Wire.requestFrom(CHRONODOT_ID, 1); | |
| byte ctrl; | |
| if(Wire.available()) { | |
| ctrl = Wire.read(); | |
| } | |
| Wire.beginTransmission(CHRONODOT_ID); | |
| Wire.write(0x0E); // control register | |
| Wire.write(ctrl & B11100011); // all bits 0; | |
| Wire.endTransmission(); | |
| //Serial << "ctrl: " << ctrl << endl; | |
| return ctrl; | |
| } | |
| void oneHzInterruptHandler(void) { | |
| //Serial.println(" TOP"); | |
| // Affichage de l'heure toutes les minutes, sauf si la luminosité vient d'être modifiée via l'encodeur | |
| if(!brightnessHasChanged) { | |
| displayNow = true; | |
| } | |
| brightnessHasChanged = false; | |
| } | |
| /** | |
| * Désactive l'affichage pour mise à jour | |
| */ | |
| void disableDisplay() { | |
| digitalWrite(DIMM_PIN, HIGH); | |
| } | |
| /** | |
| * Active l'affichage suite à mise à jour | |
| */ | |
| void enableDisplay() { | |
| analogWrite(DIMM_PIN, brightness_pwm * 16); | |
| } | |
| /** | |
| * Efface l'affichage: toutes LEDs éteintes | |
| */ | |
| void clearDisplay() { | |
| disableDisplay(); | |
| for (int i = 0; i < 4; ++i) | |
| shiftOut(DATA_PIN,CLK_PIN,LSBFIRST,B00000000); | |
| enableDisplay(); | |
| } | |
| void displayTime(WireRtcLib::tm* time) { | |
| byte digitvalue, bitfield; | |
| disableDisplay(); | |
| if(settingsMode != SET_SECONDS_MODE) { | |
| // segment minutes basses | |
| digitvalue = time->min % 10; | |
| bitfield = segments[digitvalue]; | |
| if(displayMode == SET_CLOCK_MODE) { | |
| bitfield |= 1; | |
| } | |
| shiftOut(DATA_PIN,CLK_PIN,LSBFIRST,bitfield); | |
| // segment minutes hautes | |
| digitvalue = time->min / 10; | |
| bitfield = segments[digitvalue]; | |
| shiftOut(DATA_PIN,CLK_PIN,LSBFIRST,bitfield); | |
| // segment heures basses | |
| digitvalue = time->hour % 10; | |
| bitfield = segments[digitvalue]; | |
| // on fait clignoter le décimal point | |
| if(displayMode == SET_CLOCK_MODE) { | |
| bitfield |= 1; | |
| } | |
| else { | |
| bitfield |= time->sec & 1; | |
| } | |
| //Serial.println(time->sec & 1); | |
| shiftOut(DATA_PIN,CLK_PIN,LSBFIRST,bitfield); | |
| // segment heures hautes | |
| digitvalue = time->hour / 10; | |
| // si l'heure est comprise entre 1h et 9h, on n'affiche pas le 0. | |
| bitfield = digitvalue ? segments[digitvalue] : 0; | |
| shiftOut(DATA_PIN,CLK_PIN,LSBFIRST,bitfield); | |
| } | |
| else { | |
| // segment minutes basses | |
| digitvalue = time->sec % 10; | |
| bitfield = segments[digitvalue]; | |
| if(displayMode == SET_CLOCK_MODE) { | |
| bitfield |= 1; | |
| } | |
| shiftOut(DATA_PIN,CLK_PIN,LSBFIRST,bitfield); | |
| // segment minutes hautes | |
| digitvalue = time->sec / 10; | |
| bitfield = segments[digitvalue]; | |
| shiftOut(DATA_PIN,CLK_PIN,LSBFIRST,bitfield); | |
| shiftOut(DATA_PIN,CLK_PIN,LSBFIRST,B00000000); | |
| shiftOut(DATA_PIN,CLK_PIN,LSBFIRST,B00000000); | |
| } | |
| // Les données sont envoyées, on les affiche... | |
| enableDisplay(); | |
| } | |
| void displayTemp() { | |
| float temp = getTemp(); | |
| unsigned int digits [3]; | |
| // partie entière | |
| double iValue; | |
| // partie décimale | |
| double fValue = modf(temp,&iValue); | |
| unsigned int integerValue = (unsigned int) iValue; | |
| // On tient le dernier digit à afficher | |
| unsigned int fractionValue = (unsigned int) (round(fValue * 10)); | |
| digits[2] = fractionValue; | |
| //Serial << "temp: " << temp << " => " << "integerValue: " << integerValue << " , fractionValue : " << fractionValue << endl; | |
| if(integerValue >= 10 ) { | |
| digits[1] = integerValue % 10; | |
| digits[0] = integerValue / 10; | |
| } | |
| else { | |
| digits[0] = 0; | |
| digits[1] = integerValue; | |
| } | |
| //Serial << digits[0] << digits[1] << "." << digits[2] << endl; | |
| // on se prépare à envoyer les données | |
| disableDisplay(); | |
| // le signe degré... | |
| shiftOut(DATA_PIN,CLK_PIN,LSBFIRST,B11000110); | |
| byte bitfield = segments[digits[2]]; | |
| shiftOut(DATA_PIN,CLK_PIN,LSBFIRST,bitfield); | |
| bitfield = segments[digits[1]]; | |
| bitfield |= 1; | |
| shiftOut(DATA_PIN,CLK_PIN,LSBFIRST,bitfield); | |
| bitfield = digits[0] ? segments[digits[0]] : 0; | |
| shiftOut(DATA_PIN,CLK_PIN,LSBFIRST,bitfield); | |
| // Les données sont envoyées, on les affiche... | |
| enableDisplay(); | |
| } | |
| float getTemp() { | |
| // turn DS18B20 sensor on, set HIGH | |
| //PORTC |= (1 << ONE_WIRE_POWER); | |
| digitalWrite(ONE_WIRE_POWER, HIGH); | |
| //Serial << "Requesting temperature from DS18B20... "; | |
| sensors.requestTemperatures(); | |
| float temp = sensors.getTempCByIndex(0); | |
| // turn DS18B20 off, set LOW | |
| //PORTC &= ~(1 << ONE_WIRE_POWER); | |
| digitalWrite(ONE_WIRE_POWER, LOW); | |
| //Serial << temp << endl; | |
| return temp; | |
| } | |
| DisplayMode getCurrentDisplayMode () { | |
| //uint8_t switchPin = (PIND & ((1<<PIN_CLOCK_ONLY) | (1<<PIN_TEMP_ONLY))); | |
| //Serial << "switchPin: " << switchPin << endl; | |
| //return SET_CLOCK_MODE; | |
| switch ((PIND & ((1<<PIN_CLOCK_ONLY) | (1<<PIN_TEMP_ONLY)))) { | |
| case 0x10: | |
| return TEMPERATURE_MODE; | |
| case 0x20: | |
| return CLOCK_MODE; | |
| /*case 0x30: | |
| return CLOCK_TEMP_MODE; | |
| break;*/ | |
| default: | |
| return CLOCK_TEMP_MODE; | |
| } | |
| } | |
| boolean setBrightness() { | |
| // let's read the encoder position to set the brightness | |
| int encoderValue = readEncoder(); | |
| if (encoderValue != 0) { | |
| if (previousBrightness == 15 && encoderValue == -1) | |
| brightness_pwm = 15; | |
| else if (previousBrightness == 0 && encoderValue == 1) | |
| brightness_pwm = 0; | |
| else | |
| brightness_pwm = previousBrightness - encoderValue; | |
| // display the selected brightness level: 1 - lowest, 16 highest | |
| unsigned int level = 16 - brightness_pwm; | |
| //Serial << "level: " << level << endl; | |
| unsigned int digits [3]; | |
| if(level >= 10 ) { | |
| digits[1] = level % 10; | |
| digits[0] = level / 10; | |
| } | |
| else { | |
| digits[0] = 0; | |
| digits[1] = level; | |
| } | |
| // on se prépare à envoyer les données | |
| disableDisplay(); | |
| byte bitfield = segments[digits[1]]; | |
| shiftOut(DATA_PIN,CLK_PIN,LSBFIRST,bitfield); | |
| bitfield = segments[digits[0]]; | |
| shiftOut(DATA_PIN,CLK_PIN,LSBFIRST,bitfield); | |
| shiftOut(DATA_PIN,CLK_PIN,LSBFIRST,B00000000); | |
| shiftOut(DATA_PIN,CLK_PIN,LSBFIRST,B00000000); | |
| // Les données sont envoyées, on les affiche... | |
| enableDisplay(); | |
| previousBrightness = brightness_pwm; | |
| brightnessHasChanged = true; | |
| } | |
| return brightnessHasChanged; | |
| } | |
| void handleButtonStateChanged() { | |
| uint8_t encoderButton = PINB & (1 << PB4); // reads pin 4 of port B, i.e. D12 which is the rotary encoder switch | |
| unsigned long currentMillis = millis(); | |
| if ((unsigned long)(currentMillis - millisEncButton) >= DEBOUNCE) { | |
| // We're not in the debounce period. | |
| if(encoderButton != prevEncoderButton) { | |
| //Serial << "handleButtonStateChanged" << endl; | |
| // Button state changed | |
| // Start debounce period after processing the button | |
| millisEncButton = millis(); | |
| prevEncoderButton = encoderButton; | |
| // Do the processing | |
| if (encoderButton) { | |
| //Serial << "handleButtonStateChanged" << endl; | |
| switch (displayMode) { | |
| case SET_CLOCK_MODE : | |
| if(settingsMode == SET_HOURS_MODE) { | |
| settingsMode = SET_MINUTES_MODE; | |
| } | |
| else if (settingsMode == SET_MINUTES_MODE) { | |
| settingsMode = SET_SECONDS_MODE; | |
| displayTime(settingsTime); | |
| } | |
| else if (settingsMode == SET_SECONDS_MODE) { | |
| // let's set the time on the chronodot | |
| //Serial << "setting time: " << settingsTime->hour << ":" << settingsTime->min << ":" << settingsTime->sec << endl; | |
| rtc.setTime(settingsTime); | |
| settingsMode = SETTINGS_OFF; | |
| displayMode = CLOCK_MODE; | |
| } | |
| break; | |
| default: | |
| displayMode = SET_CLOCK_MODE; | |
| settingsMode = SET_HOURS_MODE; | |
| settingsTime = rtc.getTime(); | |
| displayTime(settingsTime); | |
| break; | |
| } | |
| } | |
| /* | |
| else { | |
| // Do the low stuff. We don't care about that one as | |
| // we're interested just in the button being pressed | |
| } | |
| */ | |
| } | |
| } | |
| } | |
| long readEncoder() { | |
| long retValue = 0; | |
| long newPosition = myEnc.read(); | |
| if (newPosition != oldPosition) { | |
| if (newPosition < oldPosition) { | |
| retValue += 1; | |
| oldPosition = newPosition; | |
| } | |
| else if(newPosition >= oldPosition) { | |
| retValue -= 1; | |
| //value = value == 60 ? 0 : value; | |
| oldPosition = newPosition; | |
| } | |
| Serial << "readEncoder: " << retValue << endl; | |
| } | |
| return retValue; | |
| } | |
| void loop() { | |
| handleButtonStateChanged(); | |
| if(displayMode != SET_CLOCK_MODE) { | |
| DisplayMode currentDisplayMode = getCurrentDisplayMode(); | |
| setBrightness(); | |
| if(!brightnessHasChanged) { | |
| if (displayMode != currentDisplayMode) { | |
| // the display mode has changed! let's reset the timer... | |
| displayNow = true; | |
| displayMode = currentDisplayMode; | |
| //Serial << " =======> display mode has changed: " << displayMode << endl; | |
| } | |
| if(displayNow) { | |
| WireRtcLib::tm* now = rtc.getTime(); | |
| switch (displayMode) { | |
| case TEMPERATURE_MODE: | |
| displayTemp(); | |
| break; | |
| case CLOCK_MODE: | |
| displayTime(now); | |
| break; | |
| case CLOCK_TEMP_MODE: | |
| uint8_t seconds = now->sec; | |
| if(seconds <= 5 || seconds >= 30 && seconds <= 35) { | |
| displayTemp(); | |
| } | |
| else { | |
| displayTime(now); | |
| } | |
| } | |
| displayNow = false; | |
| } | |
| } // if(!brightnessHasChanged) | |
| } | |
| else { | |
| // SET_CLOCK_MODE | |
| //Serial << "SET_CLOCK_MODE : " << settingsMode << endl; | |
| int encoderValue = readEncoder(); | |
| if (encoderValue != 0) { | |
| switch (settingsMode) { | |
| case SET_HOURS_MODE: | |
| if (settingsTime->hour == 0 && encoderValue == -1) | |
| settingsTime->hour = 23; | |
| else if (settingsTime->hour == 23 && encoderValue == 1) | |
| settingsTime->hour = 0; | |
| else | |
| settingsTime->hour += encoderValue; | |
| break; | |
| case SET_MINUTES_MODE: | |
| if (settingsTime->min == 0 && encoderValue == -1) | |
| settingsTime->min = 59; | |
| else if (settingsTime->min == 59 && encoderValue == 1) | |
| settingsTime->min = 0; | |
| else | |
| settingsTime->min += encoderValue; | |
| break; | |
| case SET_SECONDS_MODE: | |
| if (settingsTime->sec == 0 && encoderValue == -1) | |
| settingsTime->sec = 59; | |
| else if (settingsTime->sec == 59 && encoderValue == 1) | |
| settingsTime->sec = 0; | |
| else | |
| settingsTime->sec += encoderValue; | |
| break; | |
| } | |
| displayTime(settingsTime); | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment