Don't like ads? PRO users don't see any ads ;-)
Guest

Untitled

By: a guest on Aug 8th, 2012  |  syntax: None  |  size: 11.40 KB  |  hits: 18  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. /**
  2.  * USE_GITHUB_USERNAME=nagubal
  3.  * 2.3" 4 digits 7-segment clock, using the DE-DP003 from Sure Electronics
  4.  * http://www.sure-electronics.net/mcu,display/DE-DP003.pdf
  5.  *
  6.  * The DE-DP003 is a common anode 7-segment LED display.
  7.  * The LED driver chips are composed of 4pcs of 74HC595 and 5pcs of ULN2003.
  8.  * 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.
  9.  * PWM signal can be applied on the DIMM_IN pin to control brightness.
  10.  */
  11. #include <EEPROM.h>
  12. #include <Streaming.h>
  13. #include <Wire.h>
  14.  
  15. //https://github.com/akafugu/ds_rtc_lib
  16. #include <WireRtcLib.h>
  17.  
  18. // http://www.pjrc.com/teensy/td_libs_OneWire.html
  19. #include <OneWire.h>
  20. // http://www.milesburton.com/?title=Dallas_Temperature_Control_Library
  21. #include <DallasTemperature.h>
  22.  
  23. #include "pinConstants.h"
  24.  
  25. // the DisplayMode enum declaration
  26. #include "displayMode.h"
  27.  
  28. /**
  29.  * La résolution du DS18B20; http://datasheets.maxim-ic.com/en/ds/DS18B20.pdf
  30.  */
  31. #define DS18B20_RESOLUTION 11
  32.  
  33. /**
  34.  * Default brightness
  35.  */
  36. #define DEFAULT_BRIGHTNESS 127
  37.  
  38. #define CHRONODOT_ID 0x68
  39.  
  40. /**
  41.  * Refresh display every TIME_REFRESH seconds
  42.  */
  43. #define TIME_REFRESH 1000
  44.  
  45. /**
  46.  * The current display mode
  47.  */
  48. DisplayMode displayMode = CLOCK_TEMP_MODE;
  49.  
  50. /**
  51.  * segments to be switched on for digits on 7-segments display
  52.  */
  53. byte segments[] = {
  54.   B11111100,
  55.   B01100000,
  56.   B11011010,
  57.   B11110010,
  58.   B01100110,
  59.   B10110110,
  60.   B10111110,
  61.   B11100000,
  62.   B11111110,
  63.   B11110110
  64. };
  65.  
  66. /** Timing Rollover
  67.  *  http://www.arduino.cc/playground/Code/TimingRollover
  68.  */
  69. //static unsigned long waitMillis;
  70.  
  71. static unsigned int brightness_pwm;
  72.  
  73. static unsigned int previousBrightness;
  74.  
  75. // used by the 1Hz interrupt
  76. volatile boolean displayNow = false;
  77.  
  78.  
  79. /**
  80.  * RTC based on the DS1307/DS3231SN chip connected via I2C and the Wire library
  81.  */
  82. WireRtcLib rtc;
  83.  
  84. /**
  85.  * Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
  86.  */
  87. OneWire oneWire(ONE_WIRE_BUS);
  88.  
  89. /**
  90.  * Pass our oneWire reference to Dallas Temperature.
  91.  */
  92. DallasTemperature sensors(&oneWire);
  93.  
  94. /**
  95.  * DS18B20 address
  96.  */
  97. DeviceAddress dsAddr = {  
  98.   0x28, 0x72, 0xA4, 0x93, 0x03, 0x00, 0x00, 0x49};
  99.  
  100. void setup() {
  101.   // set power pin for DS18B20 to output
  102.   pinMode(ONE_WIRE_POWER, OUTPUT);
  103.  
  104.   // Initialisation du DS1307
  105.   Wire.begin();
  106.   rtc.begin();
  107.   sensors.begin();
  108.  
  109.   brightness_pwm = DEFAULT_BRIGHTNESS;
  110.   previousBrightness = DEFAULT_BRIGHTNESS;
  111.   pinMode(DATA_PIN,OUTPUT);
  112.   pinMode(CLK_PIN,OUTPUT);
  113.   pinMode(DIMM_PIN,OUTPUT);
  114.   digitalWrite(CLK_PIN,LOW);
  115.   clearDisplay();
  116.  
  117.   // gestion du switch on-off-on
  118.   pinMode(PIN_TEMP_ONLY, INPUT);
  119.   // Turn on the internal pull-up resistor, default state is HIGH
  120.   digitalWrite(PIN_TEMP_ONLY, HIGH);
  121.   // Turn on the internal pull-up resistor, default state is HIGH
  122.   pinMode(PIN_CLOCK_ONLY, INPUT);
  123.   digitalWrite(PIN_CLOCK_ONLY, HIGH);
  124.  
  125.   // gestion du potentiomètre de luminosité  
  126.   pinMode(BRIGHTNESS_POT_PIN, INPUT);
  127.  
  128.   Serial.begin(57600);
  129.  
  130.   if(sensors.getDeviceCount() > 0) {
  131.     sensors.setResolution(DS18B20_RESOLUTION);
  132.   }
  133.  
  134.   // enable SQW, 1Hz
  135.   enableSQW();
  136.   // register interrupt function to 1Hz line
  137.   pinMode(SQW_INTERRUPT_PIN, INPUT);
  138.   // Turn on the internal pull-up resistor, default state is HIGH
  139.   digitalWrite(SQW_INTERRUPT_PIN, HIGH);
  140.   attachInterrupt(SQW_INTERRUPT_PIN - 2, oneHzInterruptHandler, FALLING); // 1  = digital pin 3, 0 = digital pin 2
  141.  
  142.   Serial.println("arduino up and running...");
  143. }
  144.  
  145. byte enableSQW(void) {
  146.   Wire.beginTransmission(CHRONODOT_ID);
  147.   Wire.write(0x0E);     // control register
  148.   Wire.endTransmission();
  149.   Wire.requestFrom(CHRONODOT_ID, 1);
  150.  
  151.   byte ctrl;
  152.   if(Wire.available()) {
  153.     ctrl = Wire.read();
  154.   }
  155.  
  156.   Wire.beginTransmission(CHRONODOT_ID);
  157.   Wire.write(0x0E);     // control register
  158.   Wire.write(ctrl & B11100011);         // all bits 0;
  159.   Wire.endTransmission();
  160.   Serial << "ctrl: " << ctrl << endl;
  161.   return ctrl;
  162. }
  163.  
  164. void oneHzInterruptHandler(void) {
  165.   //Serial.println("    TOP");
  166.   displayNow = true;
  167. }
  168.  
  169. void disableDisplay() {
  170.   digitalWrite(DIMM_PIN, HIGH);
  171. }
  172.  
  173. void enableDisplay() {
  174.   //digitalWrite(DIMM_PIN, LOW);
  175.   analogWrite(DIMM_PIN, brightness_pwm);
  176. }
  177.  
  178. void clearDisplay() {
  179.   disableDisplay();
  180.   for (int i = 0; i < 4; ++i)
  181.     shiftOut(DATA_PIN,CLK_PIN,LSBFIRST,B00000000);
  182.   //digitalWrite(DIMM_PIN,LOW);
  183.   enableDisplay();
  184. }
  185.  
  186. void displayTime(WireRtcLib::tm* time) {
  187.   byte digitvalue, bitfield;
  188.   disableDisplay();
  189.  
  190.   // segment minutes basses
  191.   digitvalue = time->min % 10;
  192.   bitfield = segments[digitvalue];
  193.   shiftOut(DATA_PIN,CLK_PIN,LSBFIRST,bitfield);
  194.  
  195.   // segment minutes hautes
  196.   digitvalue = time->min / 10;
  197.   bitfield = segments[digitvalue];
  198.   shiftOut(DATA_PIN,CLK_PIN,LSBFIRST,bitfield);
  199.  
  200.   // segment heures basses
  201.   digitvalue = time->hour % 10;
  202.   bitfield = segments[digitvalue];
  203.   // on fait clignoter le décimal point
  204.   bitfield |= time->sec & 1;
  205.   //Serial.println(time->sec & 1);
  206.   shiftOut(DATA_PIN,CLK_PIN,LSBFIRST,bitfield);
  207.  
  208.   // segment heures hautes
  209.   digitvalue = time->hour / 10;
  210.   // si l'heure est comprise entre 1h et 9h, on n'affiche pas le 0.
  211.   bitfield = digitvalue ? segments[digitvalue] : 0;
  212.   shiftOut(DATA_PIN,CLK_PIN,LSBFIRST,bitfield);
  213.  
  214.   // Les données sont envoyées, on les affiche...
  215.   enableDisplay();
  216. }
  217.  
  218. void displayTemp() {
  219.   float temp = getTemp();
  220.   unsigned int digits [3];
  221.   // partie entière
  222.   double iValue;
  223.   // partie décimale
  224.   double fValue = modf(temp,&iValue);
  225.  
  226.   unsigned int integerValue = (unsigned int) iValue;
  227.   // On tient le dernier digit à afficher
  228.   unsigned int fractionValue = (unsigned int) (round(fValue * 10));
  229.   digits[2] = fractionValue;
  230.   //Serial  << "temp: " << temp << "   =>  " << "integerValue: " << integerValue << "   , fractionValue : " << fractionValue << endl;
  231.  
  232.   if(integerValue >= 10 ) {
  233.     digits[1] = integerValue % 10;
  234.     digits[0] = integerValue / 10;
  235.   }
  236.   else {
  237.     digits[0] = 0;
  238.     digits[1] = integerValue;
  239.   }
  240.   //Serial << digits[0] << digits[1] << "." << digits[2] << endl;
  241.  
  242.   // on se prépare à envoyer les données
  243.   disableDisplay();
  244.  
  245.   // le signe degré...
  246.   shiftOut(DATA_PIN,CLK_PIN,LSBFIRST,B11000110);
  247.  
  248.   byte bitfield = segments[digits[2]];
  249.   shiftOut(DATA_PIN,CLK_PIN,LSBFIRST,bitfield);
  250.  
  251.   bitfield = segments[digits[1]];
  252.   bitfield |= 1;
  253.   shiftOut(DATA_PIN,CLK_PIN,LSBFIRST,bitfield);
  254.  
  255.   bitfield = digits[0] ? segments[digits[0]] : 0;
  256.   shiftOut(DATA_PIN,CLK_PIN,LSBFIRST,bitfield);
  257.  
  258.   // Les données sont envoyées, on les affiche...
  259.   enableDisplay();
  260. }
  261.  
  262. float getTemp() {
  263.   // turn DS18B20 sensor on
  264.   digitalWrite(ONE_WIRE_POWER, HIGH);
  265.   Serial << "Requesting temperature from DS18B20... ";
  266.   sensors.requestTemperaturesByAddress(dsAddr);
  267.   float temp = sensors.getTempC(dsAddr);
  268.   //  sensors.requestTemperatures();
  269.   //  float temp = sensors.getTempCByIndex(0);
  270.   // turn DS18B20 off
  271.   digitalWrite(ONE_WIRE_POWER, LOW);
  272.  
  273.   Serial << temp << endl;
  274.   return temp;
  275. }
  276.  
  277. DisplayMode getCurrentDisplayMode () {
  278.   int pinTempOnly = digitalRead(PIN_TEMP_ONLY);
  279.   int pinClockOnly = digitalRead(PIN_CLOCK_ONLY);
  280.   //Serial << "digitalRead(PIN_TEMP_ONLY) : " << pinTempOnly << endl;
  281.   //Serial << "digitalRead(PIN_CLOCK_ONLY) : " << pinClockOnly << endl;
  282.   if(pinTempOnly != LOW &&  pinClockOnly != LOW) {
  283.     return CLOCK_TEMP_MODE;
  284.   }
  285.   else if(pinTempOnly == LOW) {
  286.     return TEMPERATURE_MODE;
  287.   }
  288.   else if(pinClockOnly == LOW) {
  289.     return CLOCK_MODE;
  290.   }
  291. }
  292.  
  293. void dst(WireRtcLib::tm* date) {
  294.   // ++++++++++ Daylight saving cycle for Netherlands for next ten years ++++++++++
  295.   // START 2010 october
  296.   // In Netherlands/France DST only changes at the last weekend on Sunday 02:00 in MARCH and OCTOBER,
  297.   // so days between 25 and 31 is covered by this code (it is tested and seems OK)
  298.   if (date->wday == 7 && date->mon == 3 || date->mon == 10 && date->hour >1 && date->hour <4) {
  299.     // DST schedule for next ten years to october 2019 condition start in march or october
  300.  
  301.     // read Previous DST status,
  302.     int DST = EEPROM.read(1060);
  303.     //Serial << "DST (EEPROM.read(1060)): " << DST << endl;
  304.     if (date->wday == 7 && date->mon == 3 && date->mday >= 25 && date->mday <=31 && date->hour == 2 && DST==0) {
  305.       // time forward from 02:00 to 03:00 in march if DST status ==0 else don't change time!
  306.       //set the  hours to 03:00
  307.       // when status was ZERO (0) then change time from 02:00 to 03:00 hr
  308.       rtc.setTime_s(3, date->min, date->sec);
  309.       Serial << "            il est maintenant 3 heures" << endl;
  310.       // daylight saving flag
  311.       // Write DST statusflag to ONE(1) to prevent multiple changes in hours, only once in March
  312.       EEPROM.write(1060, 1);
  313.  
  314.     }
  315.     if (date->wday == 7 && date->mon == 10 && date->mday >= 25 && date->mday <=31 && date->hour == 3 && DST==1) {
  316.       // time backwards from 3:00 to 02:00 in october if DST status ==1 else don't change time!
  317.       //set the  hours to 02:00
  318.       rtc.setTime_s(2, date->min, date->sec);
  319.       Serial << "            il est maintenant 2 heures" << endl;
  320.       // daylight saving flag
  321.       // Write DST statusflag to ZERO to prevent multiple changes in hours, only once in October      
  322.       EEPROM.write(1060, 0);
  323.     }
  324.   }
  325. }
  326.  
  327. boolean setBrightness() {
  328.   static unsigned long brightMillis;
  329.   // let's read the brightness potientiometer, and map the readings for the 16 brightness levels
  330.   int valPot = analogRead(BRIGHTNESS_POT_PIN);
  331.   unsigned int mappedPot = map(valPot, 0, 1023, 0, 15);
  332.   brightness_pwm = mappedPot == 0 ? 0 : mappedPot * 16 - 1;
  333.   Serial << "valPot: " << valPot << ", mappedPot: " << mappedPot << ", brightness_pwm: " << brightness_pwm << endl;
  334.   boolean hasChanged = previousBrightness != brightness_pwm;
  335.   if (hasChanged) {
  336.     // show the selected brightness level for one second
  337.     brightMillis = millis() + TIME_REFRESH;
  338.  
  339.     // display the selected brightness level: 1 - lowest, 16 highest
  340.     unsigned int level = 16 - mappedPot;
  341.     unsigned int digits [3];
  342.     if(level >= 10 ) {
  343.       digits[1] = level % 10;
  344.       digits[0] = level / 10;
  345.     }
  346.     else {
  347.       digits[0] = 0;
  348.       digits[1] = level;
  349.     }
  350.  
  351.     // on se prépare à envoyer les données
  352.     disableDisplay();
  353.     byte bitfield = segments[digits[1]];
  354.     shiftOut(DATA_PIN,CLK_PIN,LSBFIRST,bitfield);
  355.     bitfield = segments[digits[0]];
  356.     shiftOut(DATA_PIN,CLK_PIN,LSBFIRST,bitfield);
  357.     shiftOut(DATA_PIN,CLK_PIN,LSBFIRST,B00000000);    
  358.     shiftOut(DATA_PIN,CLK_PIN,LSBFIRST,B00000000);
  359.     // Les données sont envoyées, on les affiche...
  360.     enableDisplay();
  361.     previousBrightness = brightness_pwm;
  362.   }
  363.  
  364.   return ((long)( millis() - brightMillis ) < 0);
  365. }
  366.  
  367. void loop() {
  368.   boolean brightnessHasChanged = setBrightness();
  369.   if(!brightnessHasChanged) {
  370.     DisplayMode newDisplayMode = getCurrentDisplayMode();
  371.     if (displayMode != newDisplayMode) {
  372.       // the display mode has changed! let's reset the timer...
  373.       //waitMillis = millis();
  374.       displayNow = true;
  375.       displayMode = newDisplayMode;
  376.       Serial << " =======> display mode has changed: " << displayMode << endl;
  377.     }
  378.  
  379.     //displayNow = (long)( millis() - waitMillis ) >= 0;
  380.     if(displayNow) {
  381.       WireRtcLib::tm* now = rtc.getTime();
  382.       dst(now);
  383.       switch (displayMode) {
  384.       case TEMPERATURE_MODE:
  385.         displayTemp();
  386.         break;
  387.  
  388.       case CLOCK_MODE:
  389.         displayTime(now);
  390.         break;
  391.  
  392.       case CLOCK_TEMP_MODE:
  393.         uint8_t seconds = now->sec;
  394.         if(seconds <= 5 || seconds >= 30 && seconds <= 35) {
  395.           displayTemp();
  396.         }
  397.         else {
  398.           displayTime(now);
  399.         }
  400.       }
  401.       //waitMillis += TIME_REFRESH;
  402.       displayNow = false;
  403.     }
  404.   }
  405. }