Last active
March 14, 2016 18:39
-
-
Save nagubal/f23dad55b46c0d887a0f to your computer and use it in GitHub Desktop.
A 2.3" 4 digits 7-segment arduino clock, using the DE-DP003 from Sure Electronics, and temperature reading using a DS18B20 sensor - Uses old libraries
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); | |
| } | |
| } | |
| } |
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
| // This library is free software; you can redistribute it and/or | |
| // modify it under the terms of the GNU Lesser General Public | |
| // License as published by the Free Software Foundation; either | |
| // version 2.1 of the License, or (at your option) any later version. | |
| #include "DallasTemperature.h" | |
| extern "C" { | |
| #include "Arduino.h" | |
| } | |
| DallasTemperature::DallasTemperature(OneWire* _oneWire) | |
| #if REQUIRESALARMS | |
| : _AlarmHandler(&defaultAlarmHandler) | |
| #endif | |
| { | |
| _wire = _oneWire; | |
| devices = 0; | |
| parasite = false; | |
| bitResolution = 9; | |
| waitForConversion = true; | |
| } | |
| // initialize the bus | |
| void DallasTemperature::begin(void) | |
| { | |
| DeviceAddress deviceAddress; | |
| _wire->reset_search(); | |
| devices = 0; // Reset the number of devices when we enumerate wire devices | |
| while (_wire->search(deviceAddress)) | |
| { | |
| if (validAddress(deviceAddress)) | |
| { | |
| if (!parasite && readPowerSupply(deviceAddress)) parasite = true; | |
| ScratchPad scratchPad; | |
| readScratchPad(deviceAddress, scratchPad); | |
| bitResolution = max(bitResolution, getResolution(deviceAddress)); | |
| devices++; | |
| } | |
| } | |
| } | |
| // returns the number of devices found on the bus | |
| uint8_t DallasTemperature::getDeviceCount(void) | |
| { | |
| return devices; | |
| } | |
| // returns true if address is valid | |
| bool DallasTemperature::validAddress(uint8_t* deviceAddress) | |
| { | |
| return (_wire->crc8(deviceAddress, 7) == deviceAddress[7]); | |
| } | |
| // finds an address at a given index on the bus | |
| // returns true if the device was found | |
| bool DallasTemperature::getAddress(uint8_t* deviceAddress, uint8_t index) | |
| { | |
| uint8_t depth = 0; | |
| _wire->reset_search(); | |
| while (depth <= index && _wire->search(deviceAddress)) | |
| { | |
| if (depth == index && validAddress(deviceAddress)) return true; | |
| depth++; | |
| } | |
| return false; | |
| } | |
| // attempt to determine if the device at the given address is connected to the bus | |
| bool DallasTemperature::isConnected(uint8_t* deviceAddress) | |
| { | |
| ScratchPad scratchPad; | |
| return isConnected(deviceAddress, scratchPad); | |
| } | |
| // attempt to determine if the device at the given address is connected to the bus | |
| // also allows for updating the read scratchpad | |
| bool DallasTemperature::isConnected(uint8_t* deviceAddress, uint8_t* scratchPad) | |
| { | |
| readScratchPad(deviceAddress, scratchPad); | |
| return (_wire->crc8(scratchPad, 8) == scratchPad[SCRATCHPAD_CRC]); | |
| } | |
| // read device's scratch pad | |
| void DallasTemperature::readScratchPad(uint8_t* deviceAddress, uint8_t* scratchPad) | |
| { | |
| // send the command | |
| _wire->reset(); | |
| _wire->select(deviceAddress); | |
| _wire->write(READSCRATCH); | |
| // TODO => collect all comments & use simple loop | |
| // byte 0: temperature LSB | |
| // byte 1: temperature MSB | |
| // byte 2: high alarm temp | |
| // byte 3: low alarm temp | |
| // byte 4: DS18S20: store for crc | |
| // DS18B20 & DS1822: configuration register | |
| // byte 5: internal use & crc | |
| // byte 6: DS18S20: COUNT_REMAIN | |
| // DS18B20 & DS1822: store for crc | |
| // byte 7: DS18S20: COUNT_PER_C | |
| // DS18B20 & DS1822: store for crc | |
| // byte 8: SCRATCHPAD_CRC | |
| // | |
| // for(int i=0; i<9; i++) | |
| // { | |
| // scratchPad[i] = _wire->read(); | |
| // } | |
| // read the response | |
| // byte 0: temperature LSB | |
| scratchPad[TEMP_LSB] = _wire->read(); | |
| // byte 1: temperature MSB | |
| scratchPad[TEMP_MSB] = _wire->read(); | |
| // byte 2: high alarm temp | |
| scratchPad[HIGH_ALARM_TEMP] = _wire->read(); | |
| // byte 3: low alarm temp | |
| scratchPad[LOW_ALARM_TEMP] = _wire->read(); | |
| // byte 4: | |
| // DS18S20: store for crc | |
| // DS18B20 & DS1822: configuration register | |
| scratchPad[CONFIGURATION] = _wire->read(); | |
| // byte 5: | |
| // internal use & crc | |
| scratchPad[INTERNAL_BYTE] = _wire->read(); | |
| // byte 6: | |
| // DS18S20: COUNT_REMAIN | |
| // DS18B20 & DS1822: store for crc | |
| scratchPad[COUNT_REMAIN] = _wire->read(); | |
| // byte 7: | |
| // DS18S20: COUNT_PER_C | |
| // DS18B20 & DS1822: store for crc | |
| scratchPad[COUNT_PER_C] = _wire->read(); | |
| // byte 8: | |
| // SCTRACHPAD_CRC | |
| scratchPad[SCRATCHPAD_CRC] = _wire->read(); | |
| _wire->reset(); | |
| } | |
| // writes device's scratch pad | |
| void DallasTemperature::writeScratchPad(uint8_t* deviceAddress, const uint8_t* scratchPad) | |
| { | |
| _wire->reset(); | |
| _wire->select(deviceAddress); | |
| _wire->write(WRITESCRATCH); | |
| _wire->write(scratchPad[HIGH_ALARM_TEMP]); // high alarm temp | |
| _wire->write(scratchPad[LOW_ALARM_TEMP]); // low alarm temp | |
| // DS18S20 does not use the configuration register | |
| if (deviceAddress[0] != DS18S20MODEL) _wire->write(scratchPad[CONFIGURATION]); // configuration | |
| _wire->reset(); | |
| // save the newly written values to eeprom | |
| _wire->write(COPYSCRATCH, parasite); | |
| if (parasite) delay(10); // 10ms delay | |
| _wire->reset(); | |
| } | |
| // reads the device's power requirements | |
| bool DallasTemperature::readPowerSupply(uint8_t* deviceAddress) | |
| { | |
| bool ret = false; | |
| _wire->reset(); | |
| _wire->select(deviceAddress); | |
| _wire->write(READPOWERSUPPLY); | |
| if (_wire->read_bit() == 0) ret = true; | |
| _wire->reset(); | |
| return ret; | |
| } | |
| // set resolution of all devices to 9, 10, 11, or 12 bits | |
| // if new resolution is out of range, it is constrained. | |
| void DallasTemperature::setResolution(uint8_t newResolution) | |
| { | |
| bitResolution = constrain(newResolution, 9, 12); | |
| DeviceAddress deviceAddress; | |
| for (int i=0; i<devices; i++) | |
| { | |
| getAddress(deviceAddress, i); | |
| setResolution(deviceAddress, bitResolution); | |
| } | |
| } | |
| // set resolution of a device to 9, 10, 11, or 12 bits | |
| // if new resolution is out of range, 9 bits is used. | |
| bool DallasTemperature::setResolution(uint8_t* deviceAddress, uint8_t newResolution) | |
| { | |
| ScratchPad scratchPad; | |
| if (isConnected(deviceAddress, scratchPad)) | |
| { | |
| // DS18S20 has a fixed 9-bit resolution | |
| if (deviceAddress[0] != DS18S20MODEL) | |
| { | |
| switch (newResolution) | |
| { | |
| case 12: | |
| scratchPad[CONFIGURATION] = TEMP_12_BIT; | |
| break; | |
| case 11: | |
| scratchPad[CONFIGURATION] = TEMP_11_BIT; | |
| break; | |
| case 10: | |
| scratchPad[CONFIGURATION] = TEMP_10_BIT; | |
| break; | |
| case 9: | |
| default: | |
| scratchPad[CONFIGURATION] = TEMP_9_BIT; | |
| break; | |
| } | |
| writeScratchPad(deviceAddress, scratchPad); | |
| } | |
| return true; // new value set | |
| } | |
| return false; | |
| } | |
| // returns the global resolution | |
| uint8_t DallasTemperature::getResolution() | |
| { | |
| return bitResolution; | |
| } | |
| // returns the current resolution of the device, 9-12 | |
| // returns 0 if device not found | |
| uint8_t DallasTemperature::getResolution(uint8_t* deviceAddress) | |
| { | |
| if (deviceAddress[0] == DS18S20MODEL) return 9; // this model has a fixed resolution | |
| ScratchPad scratchPad; | |
| if (isConnected(deviceAddress, scratchPad)) | |
| { | |
| switch (scratchPad[CONFIGURATION]) | |
| { | |
| case TEMP_12_BIT: | |
| return 12; | |
| break; // not needed ? | |
| case TEMP_11_BIT: | |
| return 11; | |
| break; | |
| case TEMP_10_BIT: | |
| return 10; | |
| break; | |
| case TEMP_9_BIT: | |
| return 9; | |
| break; | |
| } | |
| } | |
| return 0; | |
| } | |
| // sets the value of the waitForConversion flag | |
| // TRUE : function requestTemperature() etc returns when conversion is ready | |
| // FALSE: function requestTemperature() etc returns immediately (USE WITH CARE!!) | |
| // (1) programmer has to check if the needed delay has passed | |
| // (2) but the application can do meaningfull things in that time | |
| void DallasTemperature::setWaitForConversion(bool flag) | |
| { | |
| waitForConversion = flag; | |
| } | |
| // gets the value of the waitForConversion flag | |
| bool DallasTemperature::getWaitForConversion() | |
| { | |
| return waitForConversion; | |
| } | |
| // sends command for all devices on the bus to perform a temperature conversion | |
| void DallasTemperature::requestTemperatures() | |
| { | |
| _wire->reset(); | |
| _wire->skip(); | |
| _wire->write(STARTCONVO, parasite); | |
| // ASYNC mode? | |
| if (false == waitForConversion) return; | |
| switch (bitResolution) | |
| { | |
| case 9: | |
| delay(94); | |
| break; | |
| case 10: | |
| delay(188); | |
| break; | |
| case 11: | |
| delay(375); | |
| break; | |
| case 12: | |
| default: | |
| delay(750); | |
| break; | |
| } | |
| return; | |
| } | |
| // sends command for one device to perform a temperature by address | |
| // returns FALSE if device is disconnected | |
| // returns TRUE otherwise | |
| bool DallasTemperature::requestTemperaturesByAddress(uint8_t* deviceAddress) | |
| { | |
| // check device | |
| ScratchPad scratchPad; | |
| if (false == isConnected(deviceAddress, scratchPad)) return false; | |
| _wire->reset(); | |
| _wire->select(deviceAddress); | |
| _wire->write(STARTCONVO, parasite); | |
| // ASYNC mode? | |
| if (false == waitForConversion) return true; | |
| if (deviceAddress[0] == DS18S20MODEL) | |
| { | |
| delay(750); // max value found in datasheet | |
| return true; | |
| } | |
| // other models | |
| switch(scratchPad[CONFIGURATION]) | |
| { | |
| case TEMP_9_BIT: | |
| delay(94); | |
| break; | |
| case TEMP_10_BIT: | |
| delay(188); | |
| break; | |
| case TEMP_11_BIT: | |
| delay(375); | |
| break; | |
| case TEMP_12_BIT: | |
| default: | |
| delay(750); | |
| break; | |
| } | |
| return true; | |
| } | |
| // sends command for one device to perform a temp conversion by index | |
| bool DallasTemperature::requestTemperaturesByIndex(uint8_t deviceIndex) | |
| { | |
| DeviceAddress deviceAddress; | |
| getAddress(deviceAddress, deviceIndex); | |
| return requestTemperaturesByAddress(deviceAddress); | |
| } | |
| // Fetch temperature for device index | |
| float DallasTemperature::getTempCByIndex(uint8_t deviceIndex) | |
| { | |
| DeviceAddress deviceAddress; | |
| getAddress(deviceAddress, deviceIndex); | |
| return getTempC((uint8_t*)deviceAddress); | |
| } | |
| // Fetch temperature for device index | |
| float DallasTemperature::getTempFByIndex(uint8_t deviceIndex) | |
| { | |
| return toFahrenheit(getTempCByIndex(deviceIndex)); | |
| } | |
| // reads scratchpad and returns the temperature in degrees C | |
| float DallasTemperature::calculateTemperature(uint8_t* deviceAddress, uint8_t* scratchPad) | |
| { | |
| int16_t rawTemperature = (((int16_t)scratchPad[TEMP_MSB]) << 8) | scratchPad[TEMP_LSB]; | |
| switch (deviceAddress[0]) | |
| { | |
| case DS18B20MODEL: | |
| case DS1822MODEL: | |
| switch (scratchPad[CONFIGURATION]) | |
| { | |
| case TEMP_12_BIT: | |
| return (float)rawTemperature * 0.0625; | |
| break; | |
| case TEMP_11_BIT: | |
| return (float)(rawTemperature >> 1) * 0.125; | |
| break; | |
| case TEMP_10_BIT: | |
| return (float)(rawTemperature >> 2) * 0.25; | |
| break; | |
| case TEMP_9_BIT: | |
| return (float)(rawTemperature >> 3) * 0.5; | |
| break; | |
| } | |
| break; | |
| case DS18S20MODEL: | |
| /* | |
| Resolutions greater than 9 bits can be calculated using the data from | |
| the temperature, COUNT REMAIN and COUNT PER �C registers in the | |
| scratchpad. Note that the COUNT PER �C register is hard-wired to 16 | |
| (10h). After reading the scratchpad, the TEMP_READ value is obtained | |
| by truncating the 0.5�C bit (bit 0) from the temperature data. The | |
| extended resolution temperature can then be calculated using the | |
| following equation: | |
| COUNT_PER_C - COUNT_REMAIN | |
| TEMPERATURE = TEMP_READ - 0.25 + -------------------------- | |
| COUNT_PER_C | |
| */ | |
| // Good spot. Thanks Nic Johns for your contribution | |
| return (float)(rawTemperature >> 1) - 0.25 +((float)(scratchPad[COUNT_PER_C] - scratchPad[COUNT_REMAIN]) / (float)scratchPad[COUNT_PER_C] ); | |
| break; | |
| } | |
| } | |
| // returns temperature in degrees C or DEVICE_DISCONNECTED if the | |
| // device's scratch pad cannot be read successfully. | |
| // the numeric value of DEVICE_DISCONNECTED is defined in | |
| // DallasTemperature.h. It is a large negative number outside the | |
| // operating range of the device | |
| float DallasTemperature::getTempC(uint8_t* deviceAddress) | |
| { | |
| // TODO: Multiple devices (up to 64) on the same bus may take | |
| // some time to negotiate a response | |
| // What happens in case of collision? | |
| ScratchPad scratchPad; | |
| if (isConnected(deviceAddress, scratchPad)) return calculateTemperature(deviceAddress, scratchPad); | |
| return DEVICE_DISCONNECTED; | |
| } | |
| // returns temperature in degrees F | |
| // TODO: - when getTempC returns DEVICE_DISCONNECTED | |
| // -127 gets converted to -196.6 F | |
| float DallasTemperature::getTempF(uint8_t* deviceAddress) | |
| { | |
| return toFahrenheit(getTempC(deviceAddress)); | |
| } | |
| // returns true if the bus requires parasite power | |
| bool DallasTemperature::isParasitePowerMode(void) | |
| { | |
| return parasite; | |
| } | |
| #if REQUIRESALARMS | |
| /* | |
| ALARMS: | |
| TH and TL Register Format | |
| BIT 7 BIT 6 BIT 5 BIT 4 BIT 3 BIT 2 BIT 1 BIT 0 | |
| S 2^6 2^5 2^4 2^3 2^2 2^1 2^0 | |
| Only bits 11 through 4 of the temperature register are used | |
| in the TH and TL comparison since TH and TL are 8-bit | |
| registers. If the measured temperature is lower than or equal | |
| to TL or higher than or equal to TH, an alarm condition exists | |
| and an alarm flag is set inside the DS18B20. This flag is | |
| updated after every temperature measurement; therefore, if the | |
| alarm condition goes away, the flag will be turned off after | |
| the next temperature conversion. | |
| */ | |
| // sets the high alarm temperature for a device in degrees celsius | |
| // accepts a float, but the alarm resolution will ignore anything | |
| // after a decimal point. valid range is -55C - 125C | |
| void DallasTemperature::setHighAlarmTemp(uint8_t* deviceAddress, char celsius) | |
| { | |
| // make sure the alarm temperature is within the device's range | |
| if (celsius > 125) celsius = 125; | |
| else if (celsius < -55) celsius = -55; | |
| ScratchPad scratchPad; | |
| if (isConnected(deviceAddress, scratchPad)) | |
| { | |
| scratchPad[HIGH_ALARM_TEMP] = (uint8_t)celsius; | |
| writeScratchPad(deviceAddress, scratchPad); | |
| } | |
| } | |
| // sets the low alarm temperature for a device in degreed celsius | |
| // accepts a float, but the alarm resolution will ignore anything | |
| // after a decimal point. valid range is -55C - 125C | |
| void DallasTemperature::setLowAlarmTemp(uint8_t* deviceAddress, char celsius) | |
| { | |
| // make sure the alarm temperature is within the device's range | |
| if (celsius > 125) celsius = 125; | |
| else if (celsius < -55) celsius = -55; | |
| ScratchPad scratchPad; | |
| if (isConnected(deviceAddress, scratchPad)) | |
| { | |
| scratchPad[LOW_ALARM_TEMP] = (uint8_t)celsius; | |
| writeScratchPad(deviceAddress, scratchPad); | |
| } | |
| } | |
| // returns a char with the current high alarm temperature or | |
| // DEVICE_DISCONNECTED for an address | |
| char DallasTemperature::getHighAlarmTemp(uint8_t* deviceAddress) | |
| { | |
| ScratchPad scratchPad; | |
| if (isConnected(deviceAddress, scratchPad)) return (char)scratchPad[HIGH_ALARM_TEMP]; | |
| return DEVICE_DISCONNECTED; | |
| } | |
| // returns a char with the current low alarm temperature or | |
| // DEVICE_DISCONNECTED for an address | |
| char DallasTemperature::getLowAlarmTemp(uint8_t* deviceAddress) | |
| { | |
| ScratchPad scratchPad; | |
| if (isConnected(deviceAddress, scratchPad)) return (char)scratchPad[LOW_ALARM_TEMP]; | |
| return DEVICE_DISCONNECTED; | |
| } | |
| // resets internal variables used for the alarm search | |
| void DallasTemperature::resetAlarmSearch() | |
| { | |
| alarmSearchJunction = -1; | |
| alarmSearchExhausted = 0; | |
| for(uint8_t i = 0; i < 7; i++) | |
| alarmSearchAddress[i] = 0; | |
| } | |
| // This is a modified version of the OneWire::search method. | |
| // | |
| // Also added the OneWire search fix documented here: | |
| // http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1238032295 | |
| // | |
| // Perform an alarm search. If this function returns a '1' then it has | |
| // enumerated the next device and you may retrieve the ROM from the | |
| // OneWire::address variable. If there are no devices, no further | |
| // devices, or something horrible happens in the middle of the | |
| // enumeration then a 0 is returned. If a new device is found then | |
| // its address is copied to newAddr. Use | |
| // DallasTemperature::resetAlarmSearch() to start over. | |
| bool DallasTemperature::alarmSearch(uint8_t* newAddr) | |
| { | |
| uint8_t i; | |
| char lastJunction = -1; | |
| uint8_t done = 1; | |
| if (alarmSearchExhausted) return false; | |
| if (!_wire->reset()) return false; | |
| // send the alarm search command | |
| _wire->write(0xEC, 0); | |
| for(i = 0; i < 64; i++) | |
| { | |
| uint8_t a = _wire->read_bit( ); | |
| uint8_t nota = _wire->read_bit( ); | |
| uint8_t ibyte = i / 8; | |
| uint8_t ibit = 1 << (i & 7); | |
| // I don't think this should happen, this means nothing responded, but maybe if | |
| // something vanishes during the search it will come up. | |
| if (a && nota) return false; | |
| if (!a && !nota) | |
| { | |
| if (i == alarmSearchJunction) | |
| { | |
| // this is our time to decide differently, we went zero last time, go one. | |
| a = 1; | |
| alarmSearchJunction = lastJunction; | |
| } | |
| else if (i < alarmSearchJunction) | |
| { | |
| // take whatever we took last time, look in address | |
| if (alarmSearchAddress[ibyte] & ibit) a = 1; | |
| else | |
| { | |
| // Only 0s count as pending junctions, we've already exhasuted the 0 side of 1s | |
| a = 0; | |
| done = 0; | |
| lastJunction = i; | |
| } | |
| } | |
| else | |
| { | |
| // we are blazing new tree, take the 0 | |
| a = 0; | |
| alarmSearchJunction = i; | |
| done = 0; | |
| } | |
| // OneWire search fix | |
| // See: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1238032295 | |
| } | |
| if (a) alarmSearchAddress[ibyte] |= ibit; | |
| else alarmSearchAddress[ibyte] &= ~ibit; | |
| _wire->write_bit(a); | |
| } | |
| if (done) alarmSearchExhausted = 1; | |
| for (i = 0; i < 8; i++) newAddr[i] = alarmSearchAddress[i]; | |
| return true; | |
| } | |
| // returns true if device address has an alarm condition | |
| // TODO: can this be done with only TEMP_MSB REGISTER (faster) | |
| // if ((char) scratchPad[TEMP_MSB] <= (char) scratchPad[LOW_ALARM_TEMP]) return true; | |
| // if ((char) scratchPad[TEMP_MSB] >= (char) scratchPad[HIGH_ALARM_TEMP]) return true; | |
| bool DallasTemperature::hasAlarm(uint8_t* deviceAddress) | |
| { | |
| ScratchPad scratchPad; | |
| if (isConnected(deviceAddress, scratchPad)) | |
| { | |
| float temp = calculateTemperature(deviceAddress, scratchPad); | |
| // check low alarm | |
| if ((char)temp <= (char)scratchPad[LOW_ALARM_TEMP]) return true; | |
| // check high alarm | |
| if ((char)temp >= (char)scratchPad[HIGH_ALARM_TEMP]) return true; | |
| } | |
| // no alarm | |
| return false; | |
| } | |
| // returns true if any device is reporting an alarm condition on the bus | |
| bool DallasTemperature::hasAlarm(void) | |
| { | |
| DeviceAddress deviceAddress; | |
| resetAlarmSearch(); | |
| return alarmSearch(deviceAddress); | |
| } | |
| // runs the alarm handler for all devices returned by alarmSearch() | |
| void DallasTemperature::processAlarms(void) | |
| { | |
| resetAlarmSearch(); | |
| DeviceAddress alarmAddr; | |
| while (alarmSearch(alarmAddr)) | |
| { | |
| if (validAddress(alarmAddr)) | |
| _AlarmHandler(alarmAddr); | |
| } | |
| } | |
| // sets the alarm handler | |
| void DallasTemperature::setAlarmHandler(AlarmHandler *handler) | |
| { | |
| _AlarmHandler = handler; | |
| } | |
| // The default alarm handler | |
| void DallasTemperature::defaultAlarmHandler(uint8_t* deviceAddress) | |
| { | |
| } | |
| #endif | |
| // Convert float celsius to fahrenheit | |
| float DallasTemperature::toFahrenheit(float celsius) | |
| { | |
| return (celsius * 1.8) + 32; | |
| } | |
| // Convert float fahrenheit to celsius | |
| float DallasTemperature::toCelsius(float fahrenheit) | |
| { | |
| return (fahrenheit - 32) / 1.8; | |
| } | |
| #if REQUIRESNEW | |
| // MnetCS - Allocates memory for DallasTemperature. Allows us to instance a new object | |
| void* DallasTemperature::operator new(unsigned int size) // Implicit NSS obj size | |
| { | |
| void * p; // void pointer | |
| p = malloc(size); // Allocate memory | |
| memset((DallasTemperature*)p,0,size); // Initalise memory | |
| //!!! CANT EXPLICITLY CALL CONSTRUCTOR - workaround by using an init() methodR - workaround by using an init() method | |
| return (DallasTemperature*) p; // Cast blank region to NSS pointer | |
| } | |
| // MnetCS 2009 - Unallocates the memory used by this instance | |
| void DallasTemperature::operator delete(void* p) | |
| { | |
| DallasTemperature* pNss = (DallasTemperature*) p; // Cast to NSS pointer | |
| pNss->~DallasTemperature(); // Destruct the object | |
| free(p); // Free the memory | |
| } | |
| #endif |
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
| #ifndef DallasTemperature_h | |
| #define DallasTemperature_h | |
| #define DALLASTEMPLIBVERSION "3.7.0" | |
| // This library is free software; you can redistribute it and/or | |
| // modify it under the terms of the GNU Lesser General Public | |
| // License as published by the Free Software Foundation; either | |
| // version 2.1 of the License, or (at your option) any later version. | |
| // set to true to include code for new and delete operators | |
| #ifndef REQUIRESNEW | |
| #define REQUIRESNEW false | |
| #endif | |
| // set to true to include code implementing alarm search functions | |
| #ifndef REQUIRESALARMS | |
| #define REQUIRESALARMS true | |
| #endif | |
| #include <inttypes.h> | |
| #include <OneWire.h> | |
| // Model IDs | |
| #define DS18S20MODEL 0x10 | |
| #define DS18B20MODEL 0x28 | |
| #define DS1822MODEL 0x22 | |
| // OneWire commands | |
| #define STARTCONVO 0x44 // Tells device to take a temperature reading and put it on the scratchpad | |
| #define COPYSCRATCH 0x48 // Copy EEPROM | |
| #define READSCRATCH 0xBE // Read EEPROM | |
| #define WRITESCRATCH 0x4E // Write to EEPROM | |
| #define RECALLSCRATCH 0xB8 // Reload from last known | |
| #define READPOWERSUPPLY 0xB4 // Determine if device needs parasite power | |
| #define ALARMSEARCH 0xEC // Query bus for devices with an alarm condition | |
| // Scratchpad locations | |
| #define TEMP_LSB 0 | |
| #define TEMP_MSB 1 | |
| #define HIGH_ALARM_TEMP 2 | |
| #define LOW_ALARM_TEMP 3 | |
| #define CONFIGURATION 4 | |
| #define INTERNAL_BYTE 5 | |
| #define COUNT_REMAIN 6 | |
| #define COUNT_PER_C 7 | |
| #define SCRATCHPAD_CRC 8 | |
| // Device resolution | |
| #define TEMP_9_BIT 0x1F // 9 bit | |
| #define TEMP_10_BIT 0x3F // 10 bit | |
| #define TEMP_11_BIT 0x5F // 11 bit | |
| #define TEMP_12_BIT 0x7F // 12 bit | |
| // Error Codes | |
| #define DEVICE_DISCONNECTED -127 | |
| typedef uint8_t DeviceAddress[8]; | |
| class DallasTemperature | |
| { | |
| public: | |
| DallasTemperature(OneWire*); | |
| // initalize bus | |
| void begin(void); | |
| // returns the number of devices found on the bus | |
| uint8_t getDeviceCount(void); | |
| // returns true if address is valid | |
| bool validAddress(uint8_t*); | |
| // finds an address at a given index on the bus | |
| bool getAddress(uint8_t*, const uint8_t); | |
| // attempt to determine if the device at the given address is connected to the bus | |
| bool isConnected(uint8_t*); | |
| // attempt to determine if the device at the given address is connected to the bus | |
| // also allows for updating the read scratchpad | |
| bool isConnected(uint8_t*, uint8_t*); | |
| // read device's scratchpad | |
| void readScratchPad(uint8_t*, uint8_t*); | |
| // write device's scratchpad | |
| void writeScratchPad(uint8_t*, const uint8_t*); | |
| // read device's power requirements | |
| bool readPowerSupply(uint8_t*); | |
| // get global resolution | |
| uint8_t getResolution(); | |
| // set global resolution to 9, 10, 11, or 12 bits | |
| void setResolution(uint8_t); | |
| // returns the device resolution, 9-12 | |
| uint8_t getResolution(uint8_t*); | |
| // set resolution of a device to 9, 10, 11, or 12 bits | |
| bool setResolution(uint8_t*, uint8_t); | |
| // sets/gets the waitForConversion flag | |
| void setWaitForConversion(bool); | |
| bool getWaitForConversion(void); | |
| // sends command for all devices on the bus to perform a temperature conversion | |
| void requestTemperatures(void); | |
| // sends command for one device to perform a temperature conversion by address | |
| bool requestTemperaturesByAddress(uint8_t*); | |
| // sends command for one device to perform a temperature conversion by index | |
| bool requestTemperaturesByIndex(uint8_t); | |
| // returns temperature in degrees C | |
| float getTempC(uint8_t*); | |
| // returns temperature in degrees F | |
| float getTempF(uint8_t*); | |
| // Get temperature for device index (slow) | |
| float getTempCByIndex(uint8_t); | |
| // Get temperature for device index (slow) | |
| float getTempFByIndex(uint8_t); | |
| // returns true if the bus requires parasite power | |
| bool isParasitePowerMode(void); | |
| #if REQUIRESALARMS | |
| typedef void AlarmHandler(uint8_t*); | |
| // sets the high alarm temperature for a device | |
| // accepts a char. valid range is -55C - 125C | |
| void setHighAlarmTemp(uint8_t*, const char); | |
| // sets the low alarm temperature for a device | |
| // accepts a char. valid range is -55C - 125C | |
| void setLowAlarmTemp(uint8_t*, const char); | |
| // returns a signed char with the current high alarm temperature for a device | |
| // in the range -55C - 125C | |
| char getHighAlarmTemp(uint8_t*); | |
| // returns a signed char with the current low alarm temperature for a device | |
| // in the range -55C - 125C | |
| char getLowAlarmTemp(uint8_t*); | |
| // resets internal variables used for the alarm search | |
| void resetAlarmSearch(void); | |
| // search the wire for devices with active alarms | |
| bool alarmSearch(uint8_t*); | |
| // returns true if ia specific device has an alarm | |
| bool hasAlarm(uint8_t*); | |
| // returns true if any device is reporting an alarm on the bus | |
| bool hasAlarm(void); | |
| // runs the alarm handler for all devices returned by alarmSearch() | |
| void processAlarms(void); | |
| // sets the alarm handler | |
| void setAlarmHandler(AlarmHandler *); | |
| // The default alarm handler | |
| static void defaultAlarmHandler(uint8_t*); | |
| #endif | |
| // convert from celcius to farenheit | |
| static float toFahrenheit(const float); | |
| // convert from farenheit to celsius | |
| static float toCelsius(const float); | |
| #if REQUIRESNEW | |
| // initalize memory area | |
| void* operator new (unsigned int); | |
| // delete memory reference | |
| void operator delete(void*); | |
| #endif | |
| private: | |
| typedef uint8_t ScratchPad[9]; | |
| // parasite power on or off | |
| bool parasite; | |
| // used to determine the delay amount needed to allow for the | |
| // temperature conversion to take place | |
| int bitResolution; | |
| // used to requestTemperature with or without delay | |
| bool waitForConversion; | |
| // count of devices on the bus | |
| uint8_t devices; | |
| // Take a pointer to one wire instance | |
| OneWire* _wire; | |
| // reads scratchpad and returns the temperature in degrees C | |
| float calculateTemperature(uint8_t*, uint8_t*); | |
| #if REQUIRESALARMS | |
| // required for alarmSearch | |
| uint8_t alarmSearchAddress[8]; | |
| char alarmSearchJunction; | |
| uint8_t alarmSearchExhausted; | |
| // the alarm handler function pointer | |
| AlarmHandler *_AlarmHandler; | |
| #endif | |
| }; | |
| #endif |
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
| #include "Encoder.h" | |
| // Yes, all the code is in the header file, to provide the user | |
| // configure options with #define (before they include it), and | |
| // to facilitate some crafty optimizations! | |
| Encoder_internal_state_t * Encoder::interruptArgs[]; | |
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
| /* Encoder Library, for measuring quadrature encoded signals | |
| * http://www.pjrc.com/teensy/td_libs_Encoder.html | |
| * Copyright (c) 2011 PJRC.COM, LLC - Paul Stoffregen <[email protected]> | |
| * | |
| * Version 1.0 | |
| * | |
| * Permission is hereby granted, free of charge, to any person obtaining a copy | |
| * of this software and associated documentation files (the "Software"), to deal | |
| * in the Software without restriction, including without limitation the rights | |
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
| * copies of the Software, and to permit persons to whom the Software is | |
| * furnished to do so, subject to the following conditions: | |
| * | |
| * The above copyright notice and this permission notice shall be included in | |
| * all copies or substantial portions of the Software. | |
| * | |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
| * THE SOFTWARE. | |
| */ | |
| #ifndef Encoder_h_ | |
| #define Encoder_h_ | |
| #if defined(ARDUINO) && ARDUINO >= 100 | |
| #include "Arduino.h" | |
| #elif defined(WIRING) | |
| #include "Wiring.h" | |
| #else | |
| #include "WProgram.h" | |
| #include "pins_arduino.h" | |
| #endif | |
| #include "util/direct_pin_read.h" | |
| #if defined(ENCODER_USE_INTERRUPTS) || !defined(ENCODER_DO_NOT_USE_INTERRUPTS) | |
| #define ENCODER_USE_INTERRUPTS | |
| #define ENCODER_ARGLIST_SIZE CORE_NUM_INTERRUPT | |
| #include "util/interrupt_pins.h" | |
| #ifdef ENCODER_OPTIMIZE_INTERRUPTS | |
| #include "util/interrupt_config.h" | |
| #endif | |
| #else | |
| #define ENCODER_ARGLIST_SIZE 0 | |
| #endif | |
| // All the data needed by interrupts is consolidated into this ugly struct | |
| // to facilitate assembly language optimizing of the speed critical update. | |
| // The assembly code uses auto-incrementing addressing modes, so the struct | |
| // must remain in exactly this order. | |
| typedef struct { | |
| volatile IO_REG_TYPE * pin1_register; | |
| volatile IO_REG_TYPE * pin2_register; | |
| IO_REG_TYPE pin1_bitmask; | |
| IO_REG_TYPE pin2_bitmask; | |
| uint8_t state; | |
| int32_t position; | |
| } Encoder_internal_state_t; | |
| class Encoder | |
| { | |
| public: | |
| Encoder(uint8_t pin1, uint8_t pin2) { | |
| #ifdef INPUT_PULLUP | |
| pinMode(pin1, INPUT_PULLUP); | |
| pinMode(pin2, INPUT_PULLUP); | |
| #else | |
| pinMode(pin1, INPUT); | |
| digitalWrite(pin1, HIGH); | |
| pinMode(pin2, INPUT); | |
| digitalWrite(pin2, HIGH); | |
| #endif | |
| encoder.pin1_register = PIN_TO_BASEREG(pin1); | |
| encoder.pin1_bitmask = PIN_TO_BITMASK(pin1); | |
| encoder.pin2_register = PIN_TO_BASEREG(pin2); | |
| encoder.pin2_bitmask = PIN_TO_BITMASK(pin2); | |
| encoder.position = 0; | |
| // allow time for a passive R-C filter to charge | |
| // through the pullup resistors, before reading | |
| // the initial state | |
| delayMicroseconds(2000); | |
| uint8_t s = 0; | |
| if (DIRECT_PIN_READ(encoder.pin1_register, encoder.pin1_bitmask)) s |= 1; | |
| if (DIRECT_PIN_READ(encoder.pin2_register, encoder.pin2_bitmask)) s |= 2; | |
| encoder.state = s; | |
| #ifdef ENCODER_USE_INTERRUPTS | |
| interrupts_in_use = 0; | |
| switch (pin1) { | |
| #ifdef CORE_INT0_PIN | |
| case CORE_INT0_PIN: | |
| interruptArgs[0] = &encoder; | |
| attachInterrupt(0, isr0, CHANGE); | |
| break; | |
| #endif | |
| #ifdef CORE_INT1_PIN | |
| case CORE_INT1_PIN: | |
| interruptArgs[1] = &encoder; | |
| attachInterrupt(1, isr1, CHANGE); | |
| break; | |
| #endif | |
| #ifdef CORE_INT2_PIN | |
| case CORE_INT2_PIN: | |
| interruptArgs[2] = &encoder; | |
| attachInterrupt(2, isr2, CHANGE); | |
| break; | |
| #endif | |
| #ifdef CORE_INT3_PIN | |
| case CORE_INT3_PIN: | |
| interruptArgs[3] = &encoder; | |
| attachInterrupt(3, isr3, CHANGE); | |
| break; | |
| #endif | |
| #ifdef CORE_INT4_PIN | |
| case CORE_INT4_PIN: | |
| interruptArgs[4] = &encoder; | |
| attachInterrupt(4, isr4, CHANGE); | |
| break; | |
| #endif | |
| #ifdef CORE_INT5_PIN | |
| case CORE_INT5_PIN: | |
| interruptArgs[5] = &encoder; | |
| attachInterrupt(5, isr5, CHANGE); | |
| break; | |
| #endif | |
| #ifdef CORE_INT6_PIN | |
| case CORE_INT6_PIN: | |
| interruptArgs[6] = &encoder; | |
| attachInterrupt(6, isr6, CHANGE); | |
| break; | |
| #endif | |
| #ifdef CORE_INT7_PIN | |
| case CORE_INT7_PIN: | |
| interruptArgs[7] = &encoder; | |
| attachInterrupt(7, isr7, CHANGE); | |
| break; | |
| #endif | |
| default: | |
| return; | |
| } | |
| interrupts_in_use++; | |
| switch (pin2) { | |
| #ifdef CORE_INT0_PIN | |
| case CORE_INT0_PIN: | |
| interruptArgs[0] = &encoder; | |
| attachInterrupt(0, isr0, CHANGE); | |
| break; | |
| #endif | |
| #ifdef CORE_INT1_PIN | |
| case CORE_INT1_PIN: | |
| interruptArgs[1] = &encoder; | |
| attachInterrupt(1, isr1, CHANGE); | |
| break; | |
| #endif | |
| #ifdef CORE_INT2_PIN | |
| case CORE_INT2_PIN: | |
| interruptArgs[2] = &encoder; | |
| attachInterrupt(2, isr2, CHANGE); | |
| break; | |
| #endif | |
| #ifdef CORE_INT3_PIN | |
| case CORE_INT3_PIN: | |
| interruptArgs[3] = &encoder; | |
| attachInterrupt(3, isr3, CHANGE); | |
| break; | |
| #endif | |
| #ifdef CORE_INT4_PIN | |
| case CORE_INT4_PIN: | |
| interruptArgs[4] = &encoder; | |
| attachInterrupt(4, isr4, CHANGE); | |
| break; | |
| #endif | |
| #ifdef CORE_INT5_PIN | |
| case CORE_INT5_PIN: | |
| interruptArgs[5] = &encoder; | |
| attachInterrupt(5, isr5, CHANGE); | |
| break; | |
| #endif | |
| #ifdef CORE_INT6_PIN | |
| case CORE_INT6_PIN: | |
| interruptArgs[6] = &encoder; | |
| attachInterrupt(6, isr6, CHANGE); | |
| break; | |
| #endif | |
| #ifdef CORE_INT7_PIN | |
| case CORE_INT7_PIN: | |
| interruptArgs[7] = &encoder; | |
| attachInterrupt(7, isr7, CHANGE); | |
| break; | |
| default: | |
| return; | |
| #endif | |
| } | |
| interrupts_in_use++; | |
| #endif | |
| //update_finishup(); // to force linker to include the code | |
| } | |
| #ifdef ENCODER_USE_INTERRUPTS | |
| inline int32_t read() { | |
| if (interrupts_in_use < 2) { | |
| noInterrupts(); | |
| update(&encoder); | |
| } else { | |
| noInterrupts(); | |
| } | |
| int32_t ret = encoder.position; | |
| interrupts(); | |
| return ret; | |
| } | |
| inline void write(int32_t p) { | |
| noInterrupts(); | |
| encoder.position = p; | |
| interrupts(); | |
| } | |
| #else | |
| inline int32_t read() { | |
| update(&encoder); | |
| return encoder.position; | |
| } | |
| inline void write(int32_t p) { | |
| encoder.position = p; | |
| } | |
| #endif | |
| private: | |
| Encoder_internal_state_t encoder; | |
| #ifdef ENCODER_USE_INTERRUPTS | |
| uint8_t interrupts_in_use; | |
| #endif | |
| public: | |
| static Encoder_internal_state_t * interruptArgs[ENCODER_ARGLIST_SIZE]; | |
| // _______ _______ | |
| // Pin1 ______| |_______| |______ Pin1 | |
| // negative <--- _______ _______ __ --> positive | |
| // Pin2 __| |_______| |_______| Pin2 | |
| // new new old old | |
| // pin2 pin1 pin2 pin1 Result | |
| // ---- ---- ---- ---- ------ | |
| // 0 0 0 0 no movement | |
| // 0 0 0 1 +1 | |
| // 0 0 1 0 -1 | |
| // 0 0 1 1 +2 (assume pin1 edges only) | |
| // 0 1 0 0 -1 | |
| // 0 1 0 1 no movement | |
| // 0 1 1 0 -2 (assume pin1 edges only) | |
| // 0 1 1 1 +1 | |
| // 1 0 0 0 +1 | |
| // 1 0 0 1 -2 (assume pin1 edges only) | |
| // 1 0 1 0 no movement | |
| // 1 0 1 1 -1 | |
| // 1 1 0 0 +2 (assume pin1 edges only) | |
| // 1 1 0 1 -1 | |
| // 1 1 1 0 +1 | |
| // 1 1 1 1 no movement | |
| /* | |
| // Simple, easy-to-read "documentation" version :-) | |
| // | |
| void update(void) { | |
| uint8_t s = state & 3; | |
| if (digitalRead(pin1)) s |= 4; | |
| if (digitalRead(pin2)) s |= 8; | |
| switch (s) { | |
| case 0: case 5: case 10: case 15: | |
| break; | |
| case 1: case 7: case 8: case 14: | |
| position++; break; | |
| case 2: case 4: case 11: case 13: | |
| position--; break; | |
| case 3: case 12: | |
| position += 2; break; | |
| default: | |
| position -= 2; break; | |
| } | |
| state = (s >> 2); | |
| } | |
| */ | |
| static void update(Encoder_internal_state_t *arg) { | |
| #if defined(__AVR__) | |
| // The compiler believes this is just 1 line of code, so | |
| // it will inline this function into each interrupt | |
| // handler. That's a tiny bit faster, but grows the code. | |
| // Especially when used with ENCODER_OPTIMIZE_INTERRUPTS, | |
| // the inline nature allows the ISR prologue and epilogue | |
| // to only save/restore necessary registers, for very nice | |
| // speed increase. | |
| asm volatile ( | |
| "ld r30, X+" "\n\t" | |
| "ld r31, X+" "\n\t" | |
| "ld r24, Z" "\n\t" // r24 = pin1 input | |
| "ld r30, X+" "\n\t" | |
| "ld r31, X+" "\n\t" | |
| "ld r25, Z" "\n\t" // r25 = pin2 input | |
| "ld r30, X+" "\n\t" // r30 = pin1 mask | |
| "ld r31, X+" "\n\t" // r31 = pin2 mask | |
| "ld r22, X" "\n\t" // r22 = state | |
| "andi r22, 3" "\n\t" | |
| "and r24, r30" "\n\t" | |
| "breq L%=1" "\n\t" // if (pin1) | |
| "ori r22, 4" "\n\t" // state |= 4 | |
| "L%=1:" "and r25, r31" "\n\t" | |
| "breq L%=2" "\n\t" // if (pin2) | |
| "ori r22, 8" "\n\t" // state |= 8 | |
| "L%=2:" "ldi r30, lo8(pm(L%=table))" "\n\t" | |
| "ldi r31, hi8(pm(L%=table))" "\n\t" | |
| // "L%=2:" "ldi r30, lo8(pm(Ltable))" "\n\t" | |
| // "ldi r31, hi8(pm(Ltable))" "\n\t" | |
| "add r30, r22" "\n\t" | |
| "adc r31, __zero_reg__" "\n\t" | |
| "asr r22" "\n\t" | |
| "asr r22" "\n\t" | |
| "st X+, r22" "\n\t" // store new state | |
| "ld r22, X+" "\n\t" | |
| "ld r23, X+" "\n\t" | |
| "ld r24, X+" "\n\t" | |
| "ld r25, X+" "\n\t" | |
| "ijmp" "\n\t" // jumps to update_finishup() | |
| // TODO move this table to another static function, | |
| // so it doesn't get needlessly duplicated. Easier | |
| // said than done, due to linker issues and inlining | |
| "L%=table:" "\n\t" | |
| "rjmp L%=end" "\n\t" // 0 | |
| "rjmp L%=plus1" "\n\t" // 1 | |
| "rjmp L%=minus1" "\n\t" // 2 | |
| "rjmp L%=plus2" "\n\t" // 3 | |
| "rjmp L%=minus1" "\n\t" // 4 | |
| "rjmp L%=end" "\n\t" // 5 | |
| "rjmp L%=minus2" "\n\t" // 6 | |
| "rjmp L%=plus1" "\n\t" // 7 | |
| "rjmp L%=plus1" "\n\t" // 8 | |
| "rjmp L%=minus2" "\n\t" // 9 | |
| "rjmp L%=end" "\n\t" // 10 | |
| "rjmp L%=minus1" "\n\t" // 11 | |
| "rjmp L%=plus2" "\n\t" // 12 | |
| "rjmp L%=minus1" "\n\t" // 13 | |
| "rjmp L%=plus1" "\n\t" // 14 | |
| "rjmp L%=end" "\n\t" // 15 | |
| "L%=minus2:" "\n\t" | |
| "subi r22, 2" "\n\t" | |
| "sbci r23, 0" "\n\t" | |
| "sbci r24, 0" "\n\t" | |
| "sbci r25, 0" "\n\t" | |
| "rjmp L%=store" "\n\t" | |
| "L%=minus1:" "\n\t" | |
| "subi r22, 1" "\n\t" | |
| "sbci r23, 0" "\n\t" | |
| "sbci r24, 0" "\n\t" | |
| "sbci r25, 0" "\n\t" | |
| "rjmp L%=store" "\n\t" | |
| "L%=plus2:" "\n\t" | |
| "subi r22, 254" "\n\t" | |
| "rjmp L%=z" "\n\t" | |
| "L%=plus1:" "\n\t" | |
| "subi r22, 255" "\n\t" | |
| "L%=z:" "sbci r23, 255" "\n\t" | |
| "sbci r24, 255" "\n\t" | |
| "sbci r25, 255" "\n\t" | |
| "L%=store:" "\n\t" | |
| "st -X, r25" "\n\t" | |
| "st -X, r24" "\n\t" | |
| "st -X, r23" "\n\t" | |
| "st -X, r22" "\n\t" | |
| "L%=end:" "\n" | |
| : : "x" (arg) : "r22", "r23", "r24", "r25", "r30", "r31"); | |
| #else | |
| uint8_t p1val = DIRECT_PIN_READ(arg->pin1_register, arg->pin1_bitmask); | |
| uint8_t p2val = DIRECT_PIN_READ(arg->pin2_register, arg->pin2_bitmask); | |
| uint8_t state = arg->state & 3; | |
| if (p1val) state |= 4; | |
| if (p2val) state |= 8; | |
| arg->state = (state >> 2); | |
| switch (state) { | |
| case 1: case 7: case 8: case 14: | |
| arg->position++; | |
| return; | |
| case 2: case 4: case 11: case 13: | |
| arg->position--; | |
| return; | |
| case 3: case 12: | |
| arg->position += 2; | |
| return; | |
| case 6: case 9: | |
| arg->position += 2; | |
| return; | |
| } | |
| #endif | |
| } | |
| /* | |
| #if defined(__AVR__) | |
| // TODO: this must be a no inline function | |
| // even noinline does not seem to solve difficult | |
| // problems with this. Oh well, it was only meant | |
| // to shrink code size - there's no performance | |
| // improvement in this, only code size reduction. | |
| __attribute__((noinline)) void update_finishup(void) { | |
| asm volatile ( | |
| "ldi r30, lo8(pm(Ltable))" "\n\t" | |
| "ldi r31, hi8(pm(Ltable))" "\n\t" | |
| "Ltable:" "\n\t" | |
| "rjmp L%=end" "\n\t" // 0 | |
| "rjmp L%=plus1" "\n\t" // 1 | |
| "rjmp L%=minus1" "\n\t" // 2 | |
| "rjmp L%=plus2" "\n\t" // 3 | |
| "rjmp L%=minus1" "\n\t" // 4 | |
| "rjmp L%=end" "\n\t" // 5 | |
| "rjmp L%=minus2" "\n\t" // 6 | |
| "rjmp L%=plus1" "\n\t" // 7 | |
| "rjmp L%=plus1" "\n\t" // 8 | |
| "rjmp L%=minus2" "\n\t" // 9 | |
| "rjmp L%=end" "\n\t" // 10 | |
| "rjmp L%=minus1" "\n\t" // 11 | |
| "rjmp L%=plus2" "\n\t" // 12 | |
| "rjmp L%=minus1" "\n\t" // 13 | |
| "rjmp L%=plus1" "\n\t" // 14 | |
| "rjmp L%=end" "\n\t" // 15 | |
| "L%=minus2:" "\n\t" | |
| "subi r22, 2" "\n\t" | |
| "sbci r23, 0" "\n\t" | |
| "sbci r24, 0" "\n\t" | |
| "sbci r25, 0" "\n\t" | |
| "rjmp L%=store" "\n\t" | |
| "L%=minus1:" "\n\t" | |
| "subi r22, 1" "\n\t" | |
| "sbci r23, 0" "\n\t" | |
| "sbci r24, 0" "\n\t" | |
| "sbci r25, 0" "\n\t" | |
| "rjmp L%=store" "\n\t" | |
| "L%=plus2:" "\n\t" | |
| "subi r22, 254" "\n\t" | |
| "rjmp L%=z" "\n\t" | |
| "L%=plus1:" "\n\t" | |
| "subi r22, 255" "\n\t" | |
| "L%=z:" "sbci r23, 255" "\n\t" | |
| "sbci r24, 255" "\n\t" | |
| "sbci r25, 255" "\n\t" | |
| "L%=store:" "\n\t" | |
| "st -X, r25" "\n\t" | |
| "st -X, r24" "\n\t" | |
| "st -X, r23" "\n\t" | |
| "st -X, r22" "\n\t" | |
| "L%=end:" "\n" | |
| : : : "r22", "r23", "r24", "r25", "r30", "r31"); | |
| } | |
| #endif | |
| */ | |
| #if defined(ENCODER_USE_INTERRUPTS) && !defined(ENCODER_OPTIMIZE_INTERRUPTS) | |
| #ifdef CORE_INT0_PIN | |
| static void isr0(void) { update(interruptArgs[0]); } | |
| #endif | |
| #ifdef CORE_INT1_PIN | |
| static void isr1(void) { update(interruptArgs[1]); } | |
| #endif | |
| #ifdef CORE_INT2_PIN | |
| static void isr2(void) { update(interruptArgs[2]); } | |
| #endif | |
| #ifdef CORE_INT3_PIN | |
| static void isr3(void) { update(interruptArgs[3]); } | |
| #endif | |
| #ifdef CORE_INT4_PIN | |
| static void isr4(void) { update(interruptArgs[4]); } | |
| #endif | |
| #ifdef CORE_INT5_PIN | |
| static void isr5(void) { update(interruptArgs[5]); } | |
| #endif | |
| #ifdef CORE_INT6_PIN | |
| static void isr6(void) { update(interruptArgs[6]); } | |
| #endif | |
| #ifdef CORE_INT7_PIN | |
| static void isr7(void) { update(interruptArgs[7]); } | |
| #endif | |
| #endif | |
| }; | |
| #if defined(ENCODER_USE_INTERRUPTS) && defined(ENCODER_OPTIMIZE_INTERRUPTS) | |
| #if defined(__AVR__) | |
| #if defined(INT0_vect) && CORE_NUM_INTERRUPT > 0 | |
| ISR(INT0_vect) { Encoder::update(Encoder::interruptArgs[SCRAMBLE_INT_ORDER(0)]); } | |
| #endif | |
| #if defined(INT1_vect) && CORE_NUM_INTERRUPT > 1 | |
| ISR(INT1_vect) { Encoder::update(Encoder::interruptArgs[SCRAMBLE_INT_ORDER(1)]); } | |
| #endif | |
| #if defined(INT2_vect) && CORE_NUM_INTERRUPT > 2 | |
| ISR(INT2_vect) { Encoder::update(Encoder::interruptArgs[SCRAMBLE_INT_ORDER(2)]); } | |
| #endif | |
| #if defined(INT3_vect) && CORE_NUM_INTERRUPT > 3 | |
| ISR(INT3_vect) { Encoder::update(Encoder::interruptArgs[SCRAMBLE_INT_ORDER(3)]); } | |
| #endif | |
| #if defined(INT4_vect) && CORE_NUM_INTERRUPT > 4 | |
| ISR(INT4_vect) { Encoder::update(Encoder::interruptArgs[SCRAMBLE_INT_ORDER(4)]); } | |
| #endif | |
| #if defined(INT5_vect) && CORE_NUM_INTERRUPT > 5 | |
| ISR(INT5_vect) { Encoder::update(Encoder::interruptArgs[SCRAMBLE_INT_ORDER(5)]); } | |
| #endif | |
| #if defined(INT6_vect) && CORE_NUM_INTERRUPT > 6 | |
| ISR(INT6_vect) { Encoder::update(Encoder::interruptArgs[SCRAMBLE_INT_ORDER(6)]); } | |
| #endif | |
| #if defined(INT7_vect) && CORE_NUM_INTERRUPT > 7 | |
| ISR(INT7_vect) { Encoder::update(Encoder::interruptArgs[SCRAMBLE_INT_ORDER(7)]); } | |
| #endif | |
| #endif // AVR | |
| #endif // ENCODER_OPTIMIZE_INTERRUPTS | |
| #endif |
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 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment