Benutzer-Werkzeuge

Webseiten-Werkzeuge


elektronik:arduino_kuechenwecker

Ein Projekt für den Haushalt - Ein „Arduino based“ Küchenwecker .-)

August 2016

In Arbeit - noch nicht komplett!

Aufgabe: Küchenwecker

  • Anzeige der Zeit über ein klassisches LED Display
  • Zeiteinstellung für die wichtigsten Zeiten über einzelne Taster
  • Genaue Zeiteinstellung über einen Drehknopf mit logarithmischer Skala (d.h. die ersten Minuten können schnell genau eingestellt werden, bei längeren Zeit muss nicht lang gedreht werden )
  • Die abgelaufene Zeit wird über eine LED Ring visualisiert
  • Batterie Betrieb
  • Das ganze muss dann noch in ein Holzgehäuse passen

Fazit des ersten Versuches:

Über ein Poti die Zeit einzustellen ist zwar möglich und geht dann auch irgendwie, allerdings muss hier doch mehr Aufwand betrieben werden als im ersten Schritt geplant. Einfache ist es wohl hier einen Drehencoder einzusetzen, durch den digitalen Ansatz verspricht das ein genaueres Einstellen der gewünschten Zeit ohne großen Beschaltungsaufwand.

Das Prinzip, einfach die Spannung über den Poti mit dem integrierten AD und der Versorgungsspannung als Referenzwert zu messen, ist viel zu ungenau, die gemessenen Werte schwanken pro Messung sehr stark mit der Versorgungsspannung der Arduino.

Zu diesem Problem siehe auch Einen AD Wandler ADC0831 mit dem Raspberry PI verwenden - Verbesserung - Stabile Spannungsreferenz

Die Ursache liegt in dem leichten Schwankungen der Betriebsspannung, die mag zwar nur gering sein, hier wirkt sich das aber sehr störend aus. Eine Referenzspannungsquelle bringt hier auch nicht viel, wir hätte zwar eine stabile Referenz aber der zu messende Wert würde ja noch genauso schwanken.

Als Lösung setze ich nun eine externe Referenzspannung (LM336 2.5v) und eine stabilisierte Spannungsversorgung (LM 317, geschaltet für 2.5v) als Eingang für unseren Spannungsteiler ein. Das ist in sich stabil und damit lässt sich die Zeit „analog“ ohne große Schwankungen einstellen.

Zur Erinnerung, uns geht es ja nur darum über den Spannungsabfall die Zeit zwischen 0 und 60 einzuteilen, was wir genau messen spielt keine Rolle solange es nur schön gleichmäßig proportional ausgewertet werden kann.

Für die Eingabe vom festen Zeit Werte per Taster/Drehschalter wird auch ein analog Eingang verwendet. Am Analog Pin 2 liegt eine Kette von Widerständen (wieder über unseres stabilisierte Spannung von ~2,5V), je nach Schalterstellung ergibt sich ein Spannungsabfall aus den Werten des Widerstandsnetz und dieser wird wiederum gemessen und in die entsprechende Zeit umgesetzt. Um beide Regeln zu verwenden, wird geprüft ein Veränderung bim Poit stattfindet, wird eine Veränderung gemessen wird der Wert des Poti verwandt und nicht die Werte der Widerstandskette.

Demnächst mehr


Version 1 mit analogen Potentiometer und ein LED Display mit dem Treiber Baustein MAX7219

Material - Version 1

  • Adafruit Uno 328 5v 16Mhz
  • Potentiometer Log 1K aus der Bastelkiste
  • 7 digit 8 segment digital LED Display mit dem MAX7219

Im ersten Schritt wird das Einstellen der Zeit über ein Potentiometer realisiert, d.h. die abgefallene Spannung über den Poti wird gemessen und eine Zeit zwischen 10 Sekunden und 120*60 Sekunden umgerechnet. Das erste Ergebnis kann leider nicht überzeugen, die Messung der Spannung schwankt auch bei keiner Veränderung des Poti zu stark, daher muss auf eine Stabilisierung der Spannung gesetzt werden.

Im ersten Versuch im Sketch etwas her umgerechnet und gerundet damit das Ergebnis so einigermaßen gleichmäßig verteilt ist, das kann nun entfallen, da mit der externen Spannungsreferenz und einen Spannungsstabilisator das gelesene Ergebnis recht stabil bleibt.


Anschluss der 7 Segment Anzeige MAX72xxx

Durch den MAX7219 Chip können mit wenig Verkabelungsaufwand 8 Ziffern dargestellt werden.

5 Anschlussleitung und schon kann es losgehen:

Modul    =>    Arduino

CLK  --------> Pin  11 - Takt 
CS   --------> Pin  10 - Cip Select
DIN  --------> Pin  12 - Data In
GND  --------> GND  
VCC  --------> 5V

Die Library "LedControl" beschreibt die Programmierung und ist einfach über die Library Funktion in der IDE einbindbar.

LED Control für den MAX72xxx einbinden


Anschluss Poti

Poti =>    Arduino
1 -- ----> GND
2 -- ---->  Pin A0
3 -- ---->  5V

Spannungsversorgung des Poti mit 2,54v mit dem LM327

Schaltbild:

 LM 317 Standard Beschaltung Muss ich noch neu zeichnen, ist aus dem raspi Projekt.

Ich einen LM 317 im TO-92 Gehäuse mit 2 * 470Ohm beschaltet und ~2,54V damit erzielt.

Referenzspannung erzeugen von 2,54V mit dem LM336 2.5

Hier über zwei Dioden und einen Poti genau den gleichen Wert wie in obiger Schaltung erzielt.

Zur Vereinfachung könnte man dann wohl sogar auf die Referenz verzichten und gleich die Spannung hinter den LM337 verwenden, andersherum geht es allerdings nicht, die Referenzspannungquelle lässt sich nicht belasten!


Anschluss Start Button

Mit Pulldown Widerstand

Taster  =>    Arduino

1 --  ----> Pin 1 und GND  über -|_ 1K_|- 
2 --  ---->  5V

Anschluss Lautsprecher

Um hier etwas akustisch zu signalisieren erst mal einen Lautsprecher angeschlossen.

Lautsprecher =>    Arduino

Rot      --------> Pin 9 - PWM Pin
Schwarz  --------> GND  

Der erste Sketch für die Version 1

Noch mit einem MAX7219 Display:

//Control the MAX7219 LED Driver
#include <LedControl.h>
 
// add the 7 Segment LED 
// pin 12 is connected to the DataIn 
// pin 11 is connected to the CLK 
// pin 10 is connected to LOAD 
// only one MAX72xx Chip
// LedControl(dataPin,clockPin,csPin,numDevices)
LedControl seg71=LedControl(12,11,10,1);
 
// Port definition
const int READ_POTI_IN_PIN = 0;
const int READ_START_BUTTON_PIN=2;
const int SPEACKER_PIN=9;
 
 
// Seconds Timerange
const int TIME_RANGE=(60*60);
 
//min and max values read over the analog in
const int MIN_POTI_VALUE=0;
const int MAX_POTI_VALUE=1023;
 
//devider for one second in the range of the poti
float SEC_TICK= (float)TIME_RANGE/(float)(MAX_POTI_VALUE-MIN_POTI_VALUE);
float calc_seconds=0;
 
//var to read the poti
int poti_sum=0;
int poti_value=0;
int poti_value_last=0;
int jitter_check=0;
int jitter_ignore=3;
 
 
//time
int minutes=0;
int seconds=0;
int total_seconds=0;
 
//Buttons for the down timer 
int start_countButton=LOW;
boolean start_countdown=false;
 
 
 //----------------------
void setup() {
    // Open serial communications for debug
    Serial.begin(57600);  
    // wait for serial port to connect
    while (!Serial) {
      ; 
    }
    Serial.println("Start projekt Kitchen timer");
 
     //debug
    Serial.println("------Parameter ");
    Serial.print("TIME_RANGE :: ");
    Serial.print(TIME_RANGE);
    Serial.println(" ");
    Serial.print("SEC_TICK   :: ");
    Serial.print(SEC_TICK);
    Serial.println(" ");
 
    //Display
    //The MAX72XX is in power-saving mode on startup,
    //we have to do a wakeup call
    seg71.shutdown(0,false);  
    //Set the brightness to a medium values
    seg71.setIntensity(0,8);
    //clear the display
    seg71.clearDisplay(0);
 
    //set the internal referenz value 
    //INTERNAL
    // use the 5v power
    //DEFAULT
    //use external ref
    //EXTERNAL
    analogReference(EXTERNAL);
 
    //enable the Start count button as interrupt
    pinMode(READ_START_BUTTON_PIN, INPUT);
    // Attach the  interrupt to the ISR vector
    attachInterrupt(0, pin_ISR, RISING);
 
    //speacker
    pinMode(SPEACKER_PIN,OUTPUT);
 
}
 
//-- run
void loop() {
 
  // check if the is Button was pressed  
  if (start_countdown==true) {
     // do the countdown
     countDown(total_seconds);
  }
 
  // try to read the time input
  // unit the start button was pressed
  if (start_countdown==false) {
 
     //calculate the time  
     minutes=0;
     seconds=0;
     //first calculate in Float Values!
     calc_seconds = getPotiValue();
 
     //Float to int to get only seconds
     total_seconds=calc_seconds;
 
     //debug Serial.print("Calc Value from  poti_value:: ");
     //debug Serial.print(poti_value);
     //debug Serial.print(" calc_seconds :: ");
     //debug Serial.print(calc_seconds);
     //debug Serial.print(" total_seconds :: ");
     //debug Serial.println(total_seconds);
 
     // to hit some important values easier 
     // set the display to some important times if we are in the range of:
    switch(total_seconds){
      //0,5 min
       case 28 ... 32   : total_seconds=30;break;
      //1 min
      case 58 ... 62   : total_seconds=60*1;break;
      // 2min
      case 110 ... 130 : total_seconds=60*2;break;
      // 3min
      case 170 ... 190 : total_seconds=60*3;break;
      //4 min
      case 240 ... 250 : total_seconds=60*4;break;
      // 5min
      case 290 ... 310 : total_seconds=60*5;break;
      // 8min
      case 470 ... 490 : total_seconds=60*8;break;
      // 10min
      case 590 ... 610 : total_seconds=60*10;break;
      // 15min
      case 890 ... 910 : total_seconds=60*15;break;
      // 20min
      case 1180 ... 1220 : total_seconds=60*20;break;
      // 30min
      case 1780 ... 1820 : total_seconds=60*30;break;
      // 45min
      case 2660 ... 2740 : total_seconds=60*45;break;
      // 60min
      case 3590 ... 3620 : total_seconds=60*60;break;
    }     
 
     // set the display
     setTime(total_seconds);
     //wait 0.1 sec
     delay(50);
  }        
}
 
//interrupt method
void pin_ISR() {
   Serial.println("Start Counter was pressed");
   if (start_countdown) {
      start_countdown=false;
   }
   else {
     start_countdown=true;
   }     
}
 
 // simple speacker PWM Modulation to hear something
void bell() {
  for (int i=0;i<3;i++){
    for (unsigned char i=0; i <255; i++) {
      analogWrite(SPEACKER_PIN,i);
      delay(2);
    }
    analogWrite(SPEACKER_PIN,0);
    for (unsigned char i=255; i >0; i--) {
      analogWrite(SPEACKER_PIN,i);
      delay(2);
    }
    analogWrite(SPEACKER_PIN,0);
  }
}
 
// get the value of the poti and return the value in seconds!
// read the value of the poti to set the time
float getPotiValue(){
     // workaround against the jitter of the read values!
     // at the end with external ref and voltage regulator for the poti every thing was solved
     // at the end obsolete
     // read 5 times to the a avg value
 
     int avg_reads=5;
     poti_sum=0;
 
     for(int i=0;i<avg_reads;i++){
       // get the average Value of some time to avoid jumping values
       poti_value=analogRead(READ_POTI_IN_PIN);
       //debug Serial.print(" => get this value from the analogRead :: ");
       //debug Serial.println(poti_value);
       poti_sum=poti_sum+poti_value;       
       delay(10);       
     }
     // check if the new value is near by the old value
     jitter_check=abs((poti_sum/avg_reads) - poti_value_last);
 
     //debugSerial.print("Jitter Check:: ");
     //debugSerial.print(jitter_check);
     //debugSerial.print(" Act value :: ");
     //debugSerial.println(poti_sum/avg_reads);
 
     // if the value has not changed a lot ignore!
     if ( jitter_check > jitter_ignore) {
        poti_value=poti_sum/avg_reads;       
     }
     else {
        poti_value=poti_value_last;        
     }
     poti_value_last=poti_value;   
 
     //adjust the jitter to the range
     switch(poti_value){
          case 0             : jitter_ignore=1; break;
          case 50 ... 130    : jitter_ignore=2; break;
          case 131 ... 250   : jitter_ignore=3; break;
          case 251 ... 500   : jitter_ignore=4; break;
          case 501 ... 750   : jitter_ignore=5; break;
          case 751 ... MAX_POTI_VALUE     : jitter_ignore=6; break;
      }        
 
     //debugSerial.print("AVG Poti Value of the last 0,5 sec :: ");
     //debugSerial.print(poti_value);
     //debugSerial.print(" Last Value was :: ");
     //debugSerial.println(poti_value_last);
 
    //return seconds!
    return (float)poti_value * SEC_TICK;   
}
//count down timer
void countDown(int last_seconds){
  //loop down
  while (last_seconds!=0) {
 
     setTime(last_seconds);
     //wait one second
     delay(1000);
     if (start_countdown) {
      last_seconds=last_seconds-1;
     }
     else {
      last_seconds=0;
     }
  }  
  //stop down count
  start_countdown=false;
  printDots(100);
  bell();
}
 
 
// set time on the display
// Format Minute:Second
//
void setTime(int act_seconds){
  // calculate the Minutes 
   if (act_seconds > 59){
       minutes=act_seconds/60;
       seconds=act_seconds-(minutes*60);
   }  
   else {
      seconds=act_seconds;
      minutes=0;
   }   
   Serial.print("Time :: ");
   Serial.print(minutes);
   Serial.print("::");
   Serial.print(seconds);
   Serial.print(" -- Total Seconds :: ");
   Serial.println(act_seconds);
   // Format Minute:Second    
   printDigit(minutes,seconds);
}
 
 
 
// print dots
// pro Progress and to show the end of the timer
void printDots(int t){
   //progress dot's 
  seg71.clearDisplay(0);
  for (int i=0;i<9;i++){
    seg71.setChar(0,i,'.',false);
    delay(t);
  }
  //clear the display
  seg71.clearDisplay(0);
}
 
 
// print the time on the display
// Format Minute:Second
// t minutes , p seconds
//
void printDigit(int t,int p) {  
    int tones;  
    int ttens;  
    int pones;  
    int ptens;  
    boolean negative=false;
 
    if(t < -99 || t > 99)  
        return;  
    if(t<0) {  
        negative=true; 
        t=t*-1;  
    }    
    tones=t%10;  
    pones=p%10;      
    t=t/10;  
    p=p/10;    
    ttens=t%10;
    ptens=p%10;      
    if(negative) {  
        //print character '-' in the leftmost column  
        seg71.setChar(0,7,'-',false);  } 
    else {
        //print a blank in the sign column  
        seg71.setChar(0,7,' ',false);  
    }      
    seg71.setDigit(0,5,(byte)ttens,false); 
    seg71.setDigit(0,4,(byte)tones,true); 
    seg71.setDigit(0,3,(byte)ptens,false); 
    seg71.setDigit(0,2,(byte)pones,false);     
}


Version 2 mit dem LED Display LiteON LTC 4620HG + NeoPixel Ring und einem MP3 Modul

In der zweiten Version wird ein MAX7219 Display zerlegt um nur die Platine und den Treiber Chip zu nützen. Billiger als einen neuen MAX7219 Chip zu kaufen .-). Der Lautsprecher wird durch ein MP3 Modul ersetzt.

Material Version 2

Adafruit NeoPixel Ring

Die Drehbewegung am Poti und das Herunterzählen der Zeit wird mit einem 16* Adafruit NeoPixel Ring realisiert.

Der Adafruit NeoPixel Ring basiert auf 16 RGBW NeoPixel (5050 große LEDs) .

Diese LEDs verfügt über interne 4 LEDs (rot, grün , blau und weiß ) und einem eingebetteten Mikrocontroller, die Helligkeit und Farbe jedes R / G / B / W kann mit 8- Bit-PWM-Genauigkeit ( also 32- Bit-Farbtiefe pro Pixel) eingestellt werden.

Die LEDs sind durch Schieberegister gesteuert und es ist nur 1 digitaler Ausgang-Pin notwendig, um die erforderlichen Daten zu senden. Die PWM ist in jedem LED-Chip eingebaut, so dass die Farbe einer LED eingestellt und dieser Werte wird automatisch für jede LED weitergeführt.

Siehe Details unter https://learn.adafruit.com/adafruit-neopixel-uberguide

!Achtung

Bei der Initialisierung des Treibers für den Ring muss NEO_RGB verwendet werden!

// Which pin on the Arduino is connected to the NeoPixels?
#define PIX_PIN 6
 
// How many NeoPixels are attached to the Arduino?
#define NUMPIXELS 16
 
// When we setup the NeoPixel library, we tell it how many pixels, and which pin to use to send signals.
// Parameter 1 = number of pixels in strip
// Parameter 2 = pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
//   NEO_KHZ800  800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
//   NEO_KHZ400  400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
//   NEO_GRB     Pixels are wired for GRB bitstream (most NeoPixel products)
//   NEO_RGB     Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2) <=== This Pixel Ring !
 
Adafruit_NeoPixel pix_ring = Adafruit_NeoPixel(NUMPIXELS, PIX_PIN,  NEO_RGBW+ NEO_KHZ800);

Sound

„Klingelt“ der Küchenwecker soll diesen Melodie abgespielt werden ⇒ https://www.youtube.com/watch?v=LfPklJNNECk

Dazu wird ein MP3 Modul eingesetzt, Mein Modul MP3 GPD2846a Modul habe ich von diesem Händler erworben: http://www.ebay.de/itm/272272687227 , funktioniert und kam recht schnell (2Wochen) an.

MP3 auf eine Mini SD Karte kopieren, Lautsprecher und Spannungsversorgung an das Modul löten und dann kann es los gehen.

Übersicht:

 MP3 Modul gpd2846a anschließen

Dann wird es allerdings etwas komplizierter, die „Buttons“ für das Modul bauen auf einem Widerstandsnetz auf.

Um diese von einen Arduino zu schalten, müssen die „Buttons auf „Ground“ gezogen werden.

Dazu habe ich mich entschieden einfach eine mosfet zum Schalten zu verwenden wie in Ein einfaches LED Modul mit MOSFET 2N7002-ET1G und einer Jumpo LED.

Dann ist das schön entkoppelt und es sollte funktioniere.

Dann gleich mal los basteln und das testen.

Mehr zum Erfolg des ganzen demnächst

Die einfachste Variante ist die einfach die Versorgungsspannung zu aktivieren, dann fängt das Modul ganz automatisch an die einzige MP3 Datei auf der Karte abzuspielen, aber das ist schon fast unsportlich einfach ;-) .


Quellen

MP3 Player mit dem GPD2846A
  • Working Voltage: 3.7V Lithium Battery 600MA or 5V USB Power Supply
  • Chip:GPD2846A
  • Chip Footprint:SOP16
  • PCB Size:34.23MM*22.33MM*1MM
  • with 2W Mixed mono
  • Supports MP3 format playback
  • Supports USB audio mode
  • Supports 3 types FM radio chip : RDA5807, BK1080 and RTC6207E.
  • Does not support infrared remote control and USB device mode

Datenblatt:

Beispiele

MP3 Player mit dem gpd2856c
Diese Website verwendet Cookies. Durch die Nutzung der Website stimmen Sie dem Speichern von Cookies auf Ihrem Computer zu. Außerdem bestätigen Sie, dass Sie unsere Datenschutzbestimmungen gelesen und verstanden haben. Wenn Sie nicht einverstanden sind, verlassen Sie die Website.Weitere Information
"Autor: Gunther Pipperr"
elektronik/arduino_kuechenwecker.txt · Zuletzt geändert: 2016/08/21 16:27 von gpipperr