« Oktober 2015     Dezember 2014 »


I2C ist geil und das neue Display auchFreitag, 10 April, 2015 15:15

Das neue LCD-Display hatte ich ja bestellt, damit ich belegte Pins am Arduino einsparen kann. Heute ist es hier aufgeschlagen. Hm, wie schließe ich jetzt das I2C Display und die RTC am Arduino an? Brauche ich software-I2C, oder was? Weit gefehlt, I2C Geräte haben Namen und können alle am gleichen Bus hängen und der Treiber findet das Gerät. Super, doppelt Pins gespart!

Und das Tolle ist, die neue Bibliothek kann das Display sogar ausschalten.

Hier das erste Bild:

I2C-LCD-RTC 01

...man sieht die übrig geblieben Pins und das ist übrigens ein Powersafe als Stromversorgung und ein USB-Leistungs-Messgerät. Aktiv braucht das Ganze 0.06 Ampere.

Und hier das ganz schlafend:

I2C-LCD-RTC 02

Der Strom ist nicht mehr messbar :) 

Categories:

[ [0] Kommentare ]

Den Arduino schlafen schicken und von der RealTimeClock wieder aufweckenFreitag, 10 April, 2015 11:07

Der Arduino soll ja mal mit Batterie laufen und deswegen (und überhaupt, nicht wahr?) sind stromsparende Zustände neben der Hauptfunktion ein zweiter Hauptfaktor in der Arduino Programmierung. Wie üblich waren durch Google bereits bekannt gewordene und auch neue Webseiten diesbezüglich auskunftsfreudig.

Dass es zuerst nicht klappen wollte, den Arduino wieder auf zu wecken - schlafen schicken ging ganz wunderbar und prompt, schien zunächst undurchsichtig zu sein. Aber auch hier hatten andere Leute dasselbe Problem und so kam ich der Ursache auf die Spur. - Meine naive Annahme, wenn ich die RTC anweise, den Interrupt zu aktivieren, mit dem sie den Arduino wieder aufwecken soll, dann funktionert das auch war falsch. Vorher putzen quasi muss schon sein :)

Und eine Seite stach aus allen anderen Seiten besonders hervor, weswegen ich sie gerne hier besonders erwähne:

Gammon Forum : Electronics : Microprozessors: Power saving techniques for microprozessors 

Und hier präsentiere ich mein Labor-Script, das funktioniert (Update, für das neue LED-Display und mit 2-stelligen Ausgaben überall :) ):

    
#include <LiquidCrystal_I2C.h>
#include <DS3232RTC.h> 
#include <Time.h>
#include <Wire.h>
#include <avr/sleep.h>
#include <avr/power.h>

// old LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
int counter=0;
int pin2 = 2;

unsigned long(starttime)=2;
unsigned long(sleeptime)=1;

void setup()
{
  Serial.begin(9600);
  pinMode(pin2, INPUT); 
  lcd.begin(20, 4);
  lcd.setCursor(0,0);
  setSyncProvider(RTC.get);
  if(timeStatus() != timeSet) {
lcd.print("Unlucky - no RTC");
Serial.println("Unlucky - no RTC");
  }  
  else {
lcd.print("lucky - got RTC");
Serial.println("lucky - got RTC");
starttime=now();
sleeptime=starttime+30;
delay(2000);
  unsigned long alarmtime=sleeptime+30;
  Serial.print("Sleep time: ");
  SerialDigits(hour(sleeptime));
  Serial.print(":");
  SerialDigits(minute(sleeptime));
  Serial.print(":");
  SerialDigits(second(sleeptime));
  Serial.println("");
  Serial.print("Alarm time: ");
  SerialDigits(hour(alarmtime));
  Serial.print(":");
  SerialDigits(minute(alarmtime));
  Serial.print(":");
  SerialDigits(second(alarmtime));
  Serial.println("");
  RTC.squareWave(SQWAVE_NONE);
  RTC.alarm(1);
  RTC.alarm(2);
  RTC.alarmInterrupt(ALARM_1, true);
  RTC.alarmInterrupt(ALARM_2, false);
  RTC.setAlarm(ALM1_MATCH_HOURS, second(alarmtime), minute(alarmtime), hour(alarmtime), 0);
  Serial.println("Waiting for sleep");
  lcd.clear();
  } 
}

void loop(void)
{
  unsigned long(current)=now();
  unsigned long(soon)=current;
//  do {
 digitalClockDisplay();
//     delay(200);
 if ( (sleeptime > 1 ) and ( sleeptime = soon ) ) {
   enterSleep();
 }
//     soon=now();
//  } while ( soon  current +6);
//  do {
 digitalAlarmsDisplay();
 delay(200);
 if ( (sleeptime > 1 ) and ( sleeptime = soon ) ) {
   enterSleep();
 }
 soon=now();
//   } while ( soon   current +10);
}

void wake () {
 sleep_disable();
}
void enterSleep(void)
{
  lcd.setCursor(0,1);
  lcd.print("... entering sleep                ");
  lcd.setCursor(0,2);
  lcd.print("S1: ");
  LedDigits(hour(sleeptime));
  lcd.print(":");
  LedDigits(minute(sleeptime));
  lcd.print(":");
  LedDigits(second(sleeptime));
  lcd.setCursor(0,3);
  lcd.print("A1: ");
  LedHexes(RTC.readRTC(ALM1_HOURS));
  lcd.print(":");
  LedHexes(RTC.readRTC(ALM1_MINUTES));
  lcd.print(":");
  LedHexes(RTC.readRTC(ALM1_SECONDS));
  delay(2000);
  lcd.noBacklight();
  delay(2000);
  lcd.off();
  // disable ADC
  ADCSRA = 0;
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  sleep_enable();
  noInterrupts ();
  // This is triggered by interrupt
  attachInterrupt (0, wake, LOW);
  // turn off brown-out enable in software
  // turn on brown-out enable select
  MCUCR = bit (BODS) | bit (BODSE);
  // this must be done within 4 clock cycles of above
  MCUCR = bit (BODS);
  interrupts ();
  sleep_mode();
  
  /* After wake up continue from here. */
  
  detachInterrupt (0); 
  power_all_enable();
  lcd.on();
  sleeptime=1;
  setSyncProvider(RTC.get);
  RTC.alarmInterrupt(ALARM_1, false);
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("..just woke up!!");
  delay(2000);
}

void setAlarmOnce() {
  unsigned long alarmtime=sleeptime+60;
  Serial.print("Sleep time: ");
  SerialDigits(hour(sleeptime));
  Serial.print(":");
  SerialDigits(minute(sleeptime));
  Serial.print(":");
  SerialDigits(second(sleeptime));
  Serial.println("");
  SerialDigits(hour(alarmtime));
  Serial.print(":");
  SerialDigits(minute(alarmtime));
  Serial.print(":");
  SerialDigits(second(alarmtime));
  Serial.println("");
}

void digitalClockDisplay(void)
{
  lcd.setCursor(0,0);
  LedDigits(hour());
  lcd.print(':');
  LedDigits(minute());
  lcd.print(':');
  LedDigits(second());
  lcd.print(' ');
  char tempF[6];
  int t = RTC.temperature();
  float celsius = t / 4.0;
  dtostrf(celsius, 5, 1, tempF);
  lcd.print(celsius);
  lcd.print((char)223);
  lcd.print('C');
  lcd.setCursor(0,1);
  LedDigits(day());
  lcd.print('.');
  LedDigits(month());
  lcd.print('.');
  lcd.print(year());
  lcd.print("  ");
}

void digitalAlarmsDisplay() {
lcd.setCursor(0,2);
lcd.print("S1: ");
LedDigits(hour(sleeptime));
lcd.print(":");
LedDigits(minute(sleeptime));
lcd.print(":");
LedDigits(second(sleeptime));
lcd.setCursor(0,3);
lcd.print("A1: ");
LedHexes(RTC.readRTC(ALM1_HOURS));
lcd.print(":");
LedHexes(RTC.readRTC(ALM1_MINUTES));
lcd.print(":");
LedHexes(RTC.readRTC(ALM1_SECONDS));
lcd.print("       ");

}

void LedDigits (int digits)
{
  if(digits < 10)
lcd.print('0');
  lcd.print(digits);
}

void SerialDigits (int digits)
{
  if(digits < 10)
Serial.print('0');
  Serial.print(digits);
}

void LedHexes (int digits)
{
  if(digits < 16)
lcd.print('0');
  lcd.print(digits, HEX);
}

Etwas lang geworden :)

Categories:

[ [1] Kommentar ]

Script fur das Arduino RTCpro ModulMittwoch, 08 April, 2015 10:36

Das Folgende betrifft Arduino, eine RTC und die Umgebung ist Linux, deswegen ist es für Windows völlig nutzlos, leider.

Meine batteriegepufferte, temperaturgesteuerte Realtimeclock für den Arduino hat beim Umstecken iwie ihre Pufferung verloren und ich musste sie neu programmieren. Welche Libraries man braucht gibt es bei Adafruit, Instructables und auch anderswo zu finden. Was man auch braucht, ist die Time-Library . Und mit der kann man die Uhr (neu) programmieren. Dazu braucht man den Unixtimestamp der gewünschten Zeit und setzt ein T davor, z. B. T1428486102 für den Mi 8. Apr 09:42:27 2015 und das wird einfach über die serielle Schnittstelle zum Arduino ausgegeben. Das kann man aus der Arduino IDE oder über minicom z. B. machen - oder einfach als echo nach /dev/ttyUSB0 umleiten :)

Aber die Arduino IDE und minicom können beide keine Zeitberechnungen oder gar den Unixtimestamp ausgeben. Und weil der frisch ausgeben von date auch nicht instant verwendet werden kann, habe ich mir mal ein kleines Script gebastelt:

    
#!/bin/sh
NOW=$(date +"%s")
# wintertime
#SOON=$(( $NOW + 3601 ))
# summertime
SOON=$(( $NOW + 7201 ))
echo "Now is $NOW which is:"
date --date="@$NOW"
echo "RTC will be set to T$SOON which is:"
date --date="@$SOON"
echo -e "T$SOON\n">/dev/ttyUSB0

Es ermittelt die gegenwärtige Zeit, passt den Zeitstempel für die Uhr und einen Übertragungszeitraum an, informiert auf der Shell und gibt das gewünschte Ergebnis direkt an der seriellen Schnittstelle aus, ganz so, wie es TimeRTCSet.ino erwartet. Es ist vorbereitet, normale Zeit statt Sommerzeit aufzubereiten und wenn die serielle Schnittstelle woanders ist, muss man das auch im Script anpassen. Ist schnell und schmutzig, ich weiß. Ein schnell mal eben gemachtes Werkzeug, mehr nicht.

Categories: Elektronik, Hardware, Programmierung, Selbstgemacht

[ [0] Kommentare ]

« Oktober 2015     Dezember 2014 »