Schlagwort-Archive: Arduino

[ICStation.com] BitBastelei #243 – Si1145 Licht/IR/UV-Sensor

[ICStation.com] BitBastelei #243 - Si1145 Licht/IR/UV-Sensor

(107 MB) 00:24:19

2017-06-18 10:00 🛈

Sensorzeit: Mit dem Si1145 lassen sich so einige Werte aus dem Bereich „Licht“ erfassen: Neben der sichtbaren Lichtstärke rückt der Sensor gleich noch den Infrarot-Anteil und den aktuellen UV-Index raus. Praktisch wenn man wissen möchte, wie schnell der Sonnenbrand droht. Alles läuft mittels I²C, lässt sich also schnell mit nahezu jedem Mikrocontroller auswerten.

Das Modul von ICStation.com bringt den 2x2mm-Winzling auf ein für Bastler brauchbares Format und sorgt auch gleich noch dafür, dass die 5V eines Arduino den 3.3V-Chip nicht gleich zerstören.

Inhalt

  • 00:00 IC und Modul
  • 07:09 Si1145 an Arduino
  • 12:32 Messwerte – Si1145 vs. offizielle Werte
  • 17:07 Si1145 an ESP8266

Produkt

http://www.icstation.com/si1145-integrated-infrared-ultraviolet-sensor-module-arduino-stm32-p-10572.html

Mit dem Rabattcode: bitics gibt es 15% Rabatt

Korrekturen

Arduino betreibt die I²C-Pins immer mit internem Pull-Up, bei Nutzung eines 5V-Arduinos besteht daher die Gefahr, dass der Sensor beschädigt wird. Es sollte ein „I²C-Level-Shifter“ oder 3.3V-Mikrocontroller (3.3V-Arduino, ESP8266, etc) genutzt werden!

Weitere Links

Bild: https://www.adlerweb.info/blog/wp-content/uploads/2017/06/arduino-si1145-300×169.png

BitBastelei #236 – Arduino-Temperaturmessung mit Thermoelement & MAX6675

BitBastelei #236 - Arduino-Temperaturmessung mit Thermoelement & MAX6675

(68 MB) 00:13:55

2017-03-26 10:00 🛈

Üblicherweise nutze ich für Temperaturmessungen den DS18B20, einen 1Wire-Sensor, welcher die Temperatur digital an den genutzten Mikrocontroller übermittelt. Hat man jedoch mit höheren Temperaturen zu tun muss man sich etwas anderes suchen: Maximal 80°C sind in guter Genauigkeit möglich. Wer in heißeren Umgebungen spielt kann z.B. ein K-Thermoelement nutzen, welches vielen von ihrem Multimeter bekannt sein dürfte. Zusammen mit einem MAX6675 lassen sich auch diese einfach an Controllern nutzen.

Als Beispiel verbinde ich ein solches Thermoelement mit MAX6675, einem Arduino und einem OLED-Display um die Temperatur eines Backofens im Auge zu behalten – und das genauer als das Original-Thermostat.

Links:

BitBastelei #234 – WS2812B (Neopixel) Uhr

BitBastelei #234 - WS2812B (Neopixel) Uhr

(132 MB) 00:38:13

2017-03-12 11:00 🛈

Die WS2812B, auch bekannt als Neopixel, sind RGB-LEDs mit internem Steuer-IC, welche sich über einen einzelnen Datenpin kaskadieren und separat ansteuern lassen. Als in meinem Feed ein Angebot für ¼-Kreise mit 15 dieser LEDs durchtickerte war der Plan schnell klar: 4 ¼-Kreise á 15 LEDs macht 60 LEDs. Passend für eine Uhr. Mal schauen, ob es auch funktioniert.
Zur Zeithaltung kommt ein DS3231 zum Einsatz – ein I²C-Chip, welcher speziell für Uhren gedacht ist und genauer funktioniert als die internen Taktgeber der üblichen µCs.

Inhalt:

  • 00:00 LED-Module & Aufbauplan
  • 08:22 LED-Test mit Adafruit-Library
  • 12:32 Warum RTC statt Systemtakt / millis()?
  • 17:05 Blick auf die Software
  • 34:13 Uhr in Aktion

Code:

/**
 * NeoClock
 * 
 * Clock using 60 WS2812B/Neopixel LEDs and DS3231 RTC
 * 
 * Libraries needed:
 *   * Adafruit NeoPixel (Library Manager) - Phil Burgess / Paint Your Dragon for Adafruit Industries - LGPL3
 *   * Rtc by Makuna (Library Manager) - Michael C. Miller
 *   * Arduino Timezone Library (https://github.com/JChristensen/Timezone) - Jack Christensen - CC-BY-SA
 *   * Time Library (https://github.com/PaulStoffregen/Time) - Paul Stoffregen, Michael Margolis - LGPL2.1
 */

#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
  #include <avr/power.h>
#endif

#if defined(ESP8266)
#include <pgmspace.h>
#else
#include <avr/pgmspace.h>
#endif

#include <SoftwareWire.h>  // must be included here so that Arduino library object file references work
#include <RtcDS3231.h>

#include <Time.h>        //http://www.arduino.cc/playground/Code/Time
#include <Timezone.h>    //https://github.com/JChristensen/Timezone

#include <EEPROM.h>

//Central European Time (Frankfurt, Paris)
TimeChangeRule CEST = {"CEST", Last, Sun, Mar, 2, 120};     //Central European Summer Time
TimeChangeRule CET = {"CET ", Last, Sun, Oct, 3, 60};       //Central European Standard Time
Timezone CE(CEST, CET);

TimeChangeRule *tcr;        //pointer to the time change rule, use to get the TZ abbrev
time_t utc;

SoftwareWire myWire(8, 9);
RtcDS3231<SoftwareWire> Rtc(myWire);

#define PIN 6

unsigned long lastMillis = millis();
byte dimmer = 0x88;
byte hmark = 0;

byte ohour=0;
byte ominute=0;
byte osecond=0;

boolean fader=true;

Adafruit_NeoPixel strip = Adafruit_NeoPixel(60, PIN, NEO_GRB + NEO_KHZ800);

void setup() {

  Serial.begin(115200);
  
  strip.begin();
  strip.show(); // Initialize all pixels to 'off'

  Rtc.Begin();

  Rtc.Enable32kHzPin(false);
  Rtc.SetSquareWavePin(DS3231SquareWavePin_ModeNone); 

  if (!Rtc.GetIsRunning())
  {
      Serial.println("RTC was not actively running, starting now");
      Rtc.SetIsRunning(true);
  }

  if (!Rtc.IsDateTimeValid()) 
  {
      // Common Cuases:
      //    1) the battery on the device is low or even missing and the power line was disconnected
      Serial.println("RTC lost confidence in the DateTime!");
  }

  byte eechk = EEPROM.read(0);
  if(eechk == 0xAA) { //Assume this is our config and not a fresh chip
    dimmer = EEPROM.read(1);
    hmark = EEPROM.read(2);
    fader = EEPROM.read(3);
  }

  timeSync();
}

void calcTime(void) {
  utc = now();
  CE.toLocal(utc, &tcr);
  ohour = hour(utc);
  ominute = minute(utc);
  if(osecond != second(utc)) {
    osecond = second(utc);
    lastMillis = millis();

    if(ominute == 0 && osecond == 0) {
      //Every hour
      timeSync();
    }
  }
}

void addPixelColor(byte pixel, byte color, byte brightness) {
  color *= 8;
  uint32_t acolor = brightness;
  acolor <<= color;
  uint32_t ocolor = strip.getPixelColor(pixel);
  ocolor |= acolor;
  strip.setPixelColor(pixel, ocolor);
}

void drawClock(byte h, byte m, byte s) {  
  strip.clear();
  
  addPixelColor(m, 1, dimmer);

  if(hmark > 0) {
    for(byte i = 0; i<12; i++) {
      addPixelColor((5*i), 2, hmark);
    }
  }

  h %= 12;
  h *= 5;
  h += (m/12);
  addPixelColor(h, 2, dimmer);
  // 0x RR GG BB

  if(fader) {
    byte dim_s1 = dimmer;
    byte dim_s2 = 0;
    byte px_s2 = s+1;
    if(px_s2 >= 60) px_s2 = 0;
    unsigned long curMillis = millis()-lastMillis;
    if(curMillis < 250) {
      dim_s2 = 0;
      dim_s1 = dimmer;
    }else{
      dim_s2 = map(curMillis, 250, 1000, 0, dimmer);
      dim_s1 = dimmer - map(curMillis, 250, 1000, 0, dimmer);
    }
    
    addPixelColor(s, 0, dim_s1);
    addPixelColor(px_s2, 0, dim_s2);
  }else{
    addPixelColor(s, 0, dimmer);
  }
  
  strip.show();
}

byte rounds = 0;

void loop() {
  calcTime();

  if(rounds++ > 100) {
    Serial.print(ohour);
    Serial.print(":");
    Serial.print(ominute);
    Serial.print(":");
    Serial.println(osecond);
    rounds = 0;
  }
  
  drawClock(ohour,ominute,osecond);

  delay(10);
  
  chkSer();
}

void timeSync(void) {
  RtcDateTime dt = Rtc.GetDateTime();
  setTime(dt.Hour(),dt.Minute(),dt.Second(),dt.Day(),dt.Month(),dt.Year());
    
  Serial.print("Synced to: ");
  Serial.print(dt.Year());
  Serial.print("-");
  Serial.print(dt.Month());
  Serial.print("-");
  Serial.print(dt.Day());
  Serial.print("-");
  Serial.print(dt.Hour());
  Serial.print("-");
  Serial.print(dt.Minute());
  Serial.print("-");
  Serial.println(dt.Second());
}

void timeSave(void) {
  utc = now();
  
  RtcDateTime store = RtcDateTime(year(utc), month(utc), day(utc), hour(utc), minute(utc), second(utc));
  Rtc.SetDateTime(store);

  Serial.print("Synced to: ");
  Serial.print(year(utc));
  Serial.print("-");
  Serial.print(month(utc));
  Serial.print("-");
  Serial.print(day(utc));
  Serial.print("-");
  Serial.print(hour(utc));
  Serial.print("-");
  Serial.print(minute(utc));
  Serial.print("-");
  Serial.println(second(utc));
  
}

void setBrightness(byte brightness) {
  dimmer = brightness;
}

void chkSer(void) {
  unsigned int iy;
  byte im,id,iH,iM,iS;
  
  if(!Serial.available()) return;

  switch(Serial.read()) {
    case 'b':
      setBrightness(Serial.parseInt());
      Serial.print(F("Brightness changed to: "));
      Serial.println(dimmer);
      EEPROM.put(0, 0xAA);
      EEPROM.put(1, dimmer);
      break;
    case 't':
      iy = Serial.parseInt();
      im = Serial.parseInt();
      id = Serial.parseInt();
      iH = Serial.parseInt();
      iM = Serial.parseInt();
      iS = Serial.parseInt();
      setTime(iH,iM,iS,id,im,iy);
      Serial.println(F("System time changed"));
      break;
    case 'f':
      fader = false;
      EEPROM.put(0, 0xAA);
      EEPROM.put(3, 0);
      Serial.println(F("Fader off"));
      break;
    case 'F':
      fader = true;
      EEPROM.put(0, 0xAA);
      EEPROM.put(3, 1);
      Serial.println(F("Fader on"));
      break;
    case 'm':
      hmark = Serial.parseInt();
      EEPROM.put(0, 0xAA);
      EEPROM.put(2, hmark);
      Serial.println(F("HMark changed"));
      break;
    case 's':
      timeSync();
      Serial.println(F("Synced RTC to System"));
      break;
    case 'S':
      timeSave();
      Serial.println(F("Synced System to RTC"));
      break;
    default:
      Serial.println('?');
  }
}

Links:

BitBastelei #229 – ICStation.com RF24 Funkmodule

BitBastelei #229 - ICStation.com RF24 Funkmodule

(32 MB) 00:15:01

2017-02-05 11:00 🛈

RF24-Module sin ein guter Kompromiss um günstig und einfach Daten mit einem Mikrocontroller wie dem Arduino per Funk zu übertragen. Das Modul übernimmt dabei viele Aufgaben zur Sicherstellung einer korrekten Übertragung, sodass der µC weniger Aufgaben erledigen muss.

Mit dem Rabattcode: bitics gibt es 15% Rabatt auf das Sortiment von ICStation

BitBasics: Funk-Datenübertragung per Mikrocontroller

BitBasics: Funk-Datenübertragung per Mikrocontroller

(36 MB) 00:15:02

2017-02-05 11:00 🛈

Nicht immer kann ein ein Kabel legen um Daten eines Mikrocontrollers wie dem Arduino zu ihrem Ziel zu bringen. Hier zeige ich die bekanntesten Möglichkeiten um mit Mikrocontrollern Daten drahtlos zu übertragen.

Arch Linux / Arduino: libtinfo.so.5 fehlt

Bild: https://www.adlerweb.info/blog/wp-content/uploads/2017/02/archarduino-300×58.pngBei der Nutzung der Arduino-IDE kommt es zur Zeit unter Arch Linux zu Problemen in Zusammenhang mit AVR-Boards. Ursache ist, dass Arduino seit einigen Versionen nicht mehr die Tools des System nutzt, sondern auf vorkompilierte Binärdateien setzt. Diese Alles-dabei-Conteiner versprechen auf den ersten Blick eine Vereinfachung, fliegt aktuell leider etwas auseinander: Die beigelegten Programme sind an vielen Stellen gegen überholte Bibliotheken gebaut. Dies verschafft zwar Kompatibilität mit trägen Systemen wie z.B. Debian, macht eine Nutzung mit aktuellen Systemen umständlich.

Schaut man sich die Fehlermeldung genauer an findet man schnell heraus, dass der beigelegte avrdude die Probleme auslöst:

avrdude: error while loading shared libraries: libtinfo.so.5: cannot open shared object file: No such file or director

Libtinfo wurde zwischenzeitlich wohl in Ncurses übernommen, zudem benötigt Arduino/avrdude eine ältere, normalerweise nicht mehr installierte API der ncurses-Library.

Wer die Libraries passend haben möchte muss zuerst ncurses5-compat-libs installieren um die alten API-Versionen nachzurüsten, im Anschluss sorgt das Dummy-Paket libtinfo dafür die alten Dateinamen auf ncurses umzubiegen.

BitBastelei #224 – USB Power Monitor – Software

BitBastelei #224 - USB Power Monitor - Software

(42 MB) 00:24:11

2016-12-25 11:00 🛈

In Folge #222 hatten wir einen USB Power-Monitor gebaut, welcher Spannung und Strom misst und somit auch mAh und mWh berechnen können soll. Diesmal geht es um die Softwareseite – alles kein Hexenwerk (und vermutlich mit unzähligen Bugs), aber ein gutes Beispiel wie man verschiedene, einfache Codefragmente zu einer nützlichen Software kombinieren kann.

Quellcode:

@Github

/*
* USBMeter Test Sketch
* Copyright (c) 2017, Florian Knodt - www.adlerweb.info
* 
* Based on U8G2 HelloWorld.ino 
* Copyright (c) 2016, olikraus@gmail.com
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, 
* are permitted provided that the following conditions are met:
*
*  * Redistributions of source code must retain the above copyright notice, this list 
*    of conditions and the following disclaimer.
*    
*  * Redistributions in binary form must reproduce the above copyright notice, this 
*    list of conditions and the following disclaimer in the documentation and/or other 
*    materials provided with the distribution.
*
*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
*  CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
*  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
*  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
*  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
*  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
*  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
*  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
*  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
*  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
*  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
*  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
*  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  
*
*/

#include <Arduino.h>
#include <U8g2lib.h>

#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif

U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);   // All Boards without Reset of the Display

unsigned int ref_u = 610;
unsigned int ref_i = 412;
unsigned int ref_i_o = 145;
unsigned int ref_i_mva = 131;
unsigned int ref_DP = 615;
unsigned int ref_DN = 613;
unsigned int ref_VCC = 616;
unsigned int ref_OV = 2175;

unsigned int AA0=0;
unsigned int AA1=0;
unsigned int AA2=0;
unsigned int AA3=0;
unsigned int AA6=0;
unsigned int AA7=0;

void setup(void) {
  pinMode(2, OUTPUT);
  pinMode(3, INPUT_PULLUP);
  pinMode(4, INPUT_PULLUP);
  pinMode(5, INPUT_PULLUP);

  analogReference(INTERNAL);

  Serial.begin(115200);
  Serial.println("USBMonitor Self-Test");
  
  u8g2.begin();
}

void printV(unsigned int volt) {
  unsigned int temp = volt / 100;
  boolean srt = false;

  if(temp > 10) srt = true;
  
  u8g2.print(temp);
  u8g2.print('.');
  if(srt) {
    temp = (volt % 100) / 10;
  }else{
    temp = volt % 100;
    if(temp < 10) u8g2.print('0');
  }
  u8g2.print(temp);
}


void printV(signed int volt) {
  if(volt > 0) printV((unsigned int)volt);

  u8g2.print('-');
  volt *= -1;
  unsigned int temp = volt / 100;
  
  u8g2.print(temp);
  u8g2.print('.');
  temp = (volt % 100) / 10;
  u8g2.print(temp);
}

void loop(void) {
  u8g2.clearBuffer();					// clear the internal memory
  u8g2.setFont(u8g2_font_unifont_t_latin);	// choose a suitable font
  
  u8g2.setCursor(10, 12);
  u8g2.print("SELF-TEST-MODE");

  u8g2.setCursor(0, 26);
  u8g2.print("S1:");
  u8g2.print((digitalRead(5) ? 1 : 0));
  
  u8g2.setCursor(42, 26);
  u8g2.print("S2:");
  u8g2.print((digitalRead(4) ? 1 : 0));
  
  u8g2.setCursor(85, 26);
  u8g2.print("S3:");
  u8g2.print((digitalRead(3) ? 1 : 0));

  u8g2.setCursor(0, 37);
  u8g2.print("A0:");
  //u8g2.print(analogRead(A0));
  unsigned int adco = (float)analogReadCache(AA0) * ref_u / 1000;
  printV(adco);

  u8g2.setCursor(64, 37);
  u8g2.print("A1:");
  //u8g2.print(analogRead(A1));
  signed int itmp=0;
  adco = (float)analogReadCache(AA1) * ref_i / 1000;
  itmp = adco - ref_i_o;
  itmp *= ref_i_mva;
  itmp /= 10;
  printV(itmp);

  u8g2.setCursor(0, 48);
  u8g2.print("A2:");
  //u8g2.print(analogRead(A2));
  adco = (float)analogReadCache(AA2) * ref_DP / 1000;
  printV(adco);

  u8g2.setCursor(64, 48);
  u8g2.print("A3:");
  //u8g2.print(analogRead(A3));
  adco = (float)analogReadCache(AA3) * ref_DN / 1000;
  printV(adco);

  u8g2.setCursor(0, 59);
  u8g2.print("A6:");
  //u8g2.print(analogRead(A6));
  adco = (float)analogReadCache(AA6) * ref_OV / 1000;
  printV(adco);

  u8g2.setCursor(64, 59);
  u8g2.print("A7:");
  //u8g2.print(analogRead(A7));
  adco = (float)analogReadCache(AA7) * ref_VCC / 1000;
  printV(adco);

  Serial.print((AA0));
  Serial.print(';');
  Serial.print((AA1));
  Serial.print(';');
  Serial.print((AA2));
  Serial.print(';');
  Serial.print((AA3));
  Serial.print(';');
  Serial.print((AA6));
  Serial.print(';');
  Serial.print((AA7));
  Serial.print(';');
  Serial.print(itmp);
  Serial.println();
    
  u8g2.sendBuffer();					// transfer internal memory to the display

  if(Serial.available() > 0) {
    char in = Serial.read();
    switch(in) {
      case '1':
      case 1:
        digitalWrite(2, HIGH);
        Serial.println("o1");
        break;
      case '0':
      case 0:
        digitalWrite(2, LOW);
        Serial.println("o0");
        break;
        
    }
  }

  //Wait 100ms to next display
  unsigned long lct = millis() + 500;
  while(millis() <= lct) {
    AA0 = (AA0 + (analogRead(A0)*10)) / 2;
    AA1 = (AA1 + (analogRead(A1)*10)) / 2;
    AA2 = (AA2 + (analogRead(A2)*10)) / 2;
    AA3 = (AA3 + (analogRead(A3)*10)) / 2;
    AA6 = (AA6 + (analogRead(A6)*10)) / 2;
    AA7 = (AA7 + (analogRead(A7)*10)) / 2;
  }
}

unsigned int analogReadCache(unsigned int out) {
  return out/10;
}
/*
* USBMeter Test Sketch
* Copyright (c) 2017, Florian Knodt - www.adlerweb.info
* 
* Based on U8G2 HelloWorld.ino 
* Copyright (c) 2016, olikraus@gmail.com
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, 
* are permitted provided that the following conditions are met:
*
*  * Redistributions of source code must retain the above copyright notice, this list 
*    of conditions and the following disclaimer.
*    
*  * Redistributions in binary form must reproduce the above copyright notice, this 
*    list of conditions and the following disclaimer in the documentation and/or other 
*    materials provided with the distribution.
*
*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
*  CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
*  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
*  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
*  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
*  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
*  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
*  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
*  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
*  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
*  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
*  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
*  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  
*
*/

#include <Arduino.h>
#include <U8g2lib.h>
#include <Wire.h>
#include <EEPROM.h>

U8G2_SSD1306_128X64_NONAME_1_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);   // All Boards without Reset of the Display

//#define DEBUG

#define LED 13
#define FET 2
#define SW 3
#define RE1 4
#define RE2 5

#define ADC_U A0
#define ADC_I A1
#define ADC_DP A3
#define ADC_DN A2
#define ADC_VCC A7
#define ADC_OV A6

#define BROWNOUT 0 //4.6V - write EEPROM and shut down

static const float version = 0.02;

unsigned long lasttime = millis();
unsigned int runtime=0;

unsigned long lastkey = 0;
boolean lastkeyact = false;

unsigned int u_min = 475;
unsigned int u_max = 525;

unsigned int ref_u = 610;

/*
 * 10A

  unsigned int ref_i = 497;
  unsigned int ref_i_o = 174;
  unsigned int ref_i_mva = 146;
*/

/*
 * 5A
*/
  unsigned int ref_i = 412;
  unsigned int ref_i_o = 145;
  unsigned int ref_i_mva = 131;
/**/

unsigned int ref_DP = 615;
unsigned int ref_DN = 613;
unsigned int ref_VCC = 616;
unsigned int ref_OV = 2175;

unsigned int volt=0;
signed int amp=0;
signed int mAh=0;
signed long mWh=0;

char mAh_c=0;
char mWh_c=0;

unsigned int lastVcc=0;

unsigned int DP=0;
unsigned int DN=0;

byte signaling = 0; //0=open; 1=data; 2=apple-500; 3=Apple-1000; 4=Apple-2000; 5=DCP

/*
 * When D+ = D? = 2.0 V, the device may pull up to 500 mA.
 * When D+ = 2.0 V and D? = 2.8 V, the device may pull up to 1 A of current.
 * When D+ = 2.8 V and D? = 2.0 V, the device may pull up to 2 A of current.
 */

char flags[4];
byte uov = 0;
byte uovAct = 0;

byte menu = 0;
byte menuAct = 0;
char uartBtn = 0x00;

unsigned int adc_u = 0;
unsigned int adc_i = 0;
unsigned int adc_DP = 0;
unsigned int adc_DN = 0;
unsigned int adc_VCC = 0;
unsigned int adc_OV = 0;

boolean running = false;
boolean output = false;

void setup() {
  unsigned int tRead=0;
  
  // put your setup code here, to run once:
  pinMode(LED, OUTPUT);
  pinMode(FET, OUTPUT);

  pinMode(SW, INPUT_PULLUP);
  pinMode(RE1, INPUT_PULLUP);
  pinMode(RE2, INPUT_PULLUP);

  pinMode(ADC_U, INPUT);
  pinMode(ADC_I, INPUT);
  pinMode(ADC_DP, INPUT);
  pinMode(ADC_DN, INPUT);
  pinMode(ADC_VCC, INPUT);
  pinMode(ADC_OV, INPUT);

  digitalWrite(LED, LOW);
  digitalWrite(FET, LOW);
  digitalWrite(ADC_U, LOW);
  digitalWrite(ADC_I, LOW);
  digitalWrite(ADC_DP, LOW);
  digitalWrite(ADC_DN, LOW);
  digitalWrite(ADC_VCC, LOW);
  digitalWrite(ADC_OV, LOW);

  analogReference(INTERNAL); //1.1V internal bandgap reference

  EEPROM.get(0, tRead);
  if(tRead > 0x0000 && tRead < 0xFFFF) u_min = tRead;
  EEPROM.get(2, tRead);
  if(tRead > 0x0000 && tRead < 0xFFFF) u_max = tRead;
  EEPROM.get(4, tRead);
  if(tRead > 0x0000 && tRead < 0xFFFF) ref_u = tRead;
  EEPROM.get(6, tRead);
  if(tRead > 0x0000 && tRead < 0xFFFF) ref_i = tRead;
  EEPROM.get(8, tRead);
  if(tRead > 0x0000 && tRead < 0xFFFF) ref_DP = tRead;
  EEPROM.get(10, tRead);
  if(tRead > 0x0000 && tRead < 0xFFFF) ref_DN = tRead;
  EEPROM.get(12, tRead);
  if(tRead > 0x0000 && tRead < 0xFFFF) ref_VCC = tRead;
  EEPROM.get(14, tRead);
  if(tRead > 0x0000 && tRead < 0xFFFF) ref_OV = tRead;
  EEPROM.get(16, tRead);
  if(tRead > 0x0000 && tRead < 0xFFFF) mAh = tRead;
  EEPROM.get(18, tRead);
  if(tRead > 0x0000 && tRead < 0xFFFF) mWh = tRead;
  EEPROM.get(22, tRead);
  if(tRead > 0x0000 && tRead < 0xFFFF) runtime = tRead;
  
  Serial.begin(115200);

  Serial.println(F("#BOOT"));
  Serial.println(F("#USB POWER Monitor - www.adlerweb.info"));
  Serial.print(F("#Version: "));
  Serial.println(version);

  Serial.print(F("#[C] uMin: "));
  Serial.println(u_min);
  Serial.print(F("#[C] uMax: "));
  Serial.println(u_max);
  Serial.print(F("#[C] ref_u: "));
  Serial.println(ref_u);
  Serial.print(F("#[C] ref_i: "));
  Serial.println(ref_i);
  Serial.print(F("#[C] ref_DP: "));
  Serial.println(ref_DP);
  Serial.print(F("#[C] ref_DN: "));
  Serial.println(ref_DN);
  Serial.print(F("#[C] ref_VCC: "));
  Serial.println(ref_VCC);
  Serial.print(F("#[C] ref_OV: "));
  Serial.println(ref_OV);
  Serial.print(F("#[C] mAh: "));
  Serial.println(mAh);
  Serial.print(F("#[C] mWh: "));
  Serial.println(mWh);
  Serial.print(F("#[C] runtime: "));
  Serial.println(runtime);
  
  u8g2.begin();
  u8g2.firstPage();

  do {
    u8g2.setFont(u8g2_font_6x13_tr);
    u8g2.drawStr(11,13,"USB POWER MONITOR");
    u8g2.drawStr(11,25,"www.adlerweb.info");
  
    String out;
    out = "Version: ";
    out += version;
  
    char outc[out.length()+1];
    out.toCharArray(outc, sizeof(outc));
  
    u8g2.drawStr(25,50,outc);
  } while ( u8g2.nextPage() );

  delay(1000);
}


void dbug(String str) {
  #ifdef DEBUG
    Serial.print("D:");
    Serial.println(str);
  #endif
}


void loop() {
  unsigned int passed = (millis()-lasttime)/1000;
  
  getReadings();
  checkVcc();
  procUART();
  procSwitch();
  
  if(!u8g2.nextPage() && (millis()-lasttime)/1000 > 0) {
    dbug("FRAME");
    
    if(running && runtime < 0xFFFF) {
      runtime += (millis()-lasttime)/1000;
    }

    lasttime = millis();

    u8g2.firstPage();

    volt = procVolt();
    amp = procAmp();
    procmAh(passed);
    procmWh(passed);

    procDP();
    procDN();
    procSignaling();

    flags[0] = 'C';
    if(running) flags[0] = 'D';
    flags[1] = 'Q';
    if(output) flags[1] = 'S';
    
    switch(signaling) {
      case 1: //Data
        flags[2] = 'f';
        break;
      case 2: //Apple 0.5
      case 3: //Apple 1.0
      case 4: //Apple 2.0
        flags[2] = 'I';
        break;
      case 5: //DCP
        flags[2] = 'J';
        break;
      default: //0=OPEN
        flags[2] = 'H';
    }

    uovAct = uov;
    menuAct = menu;
    
    Serial.print('!');
    Serial.print(volt);
    Serial.print(';');
    Serial.print(amp);
    Serial.print(';');
    Serial.print(mAh);
    Serial.print(';');
    Serial.print(mWh);
    Serial.print(';');
    Serial.print(runtime);
    Serial.print(';');
    Serial.print(running);
    Serial.print(';');
    Serial.print(output);
    Serial.print(';');
    Serial.print(signaling);
    Serial.print(';');
    Serial.print(lastVcc);
    Serial.println();
  }

  switch(menuAct) {
    case 0:
      u8g2.setFont(u8g2_font_6x13_tr);
      u8g2.drawStr(38,13,"USB PWR MONITOR");
    
      drawVolt();
      drawAmp();
    
      drawWatt();
      
      drawAh();
      drawWh();
      
      drawTime(runtime);
    
      switch(uovAct) {
        case 1:
          u8g2.drawStr(115,63,"UV");
          break;
        case 2:
          u8g2.drawStr(115,63,"OV");
          break;
      }
    
      u8g2.setFont(u8g2_font_m2icon_9_tf);
      u8g2.drawStr(0,11,flags);
      break;
    case 1:
      u8g2.setFont(u8g2_font_6x13_tr);
      u8g2.drawStr(38,13,"USB PWR MONITOR");

      drawDP();
      drawDN();
      drawSignaling();
      drawVCC();
      
      u8g2.setFont(u8g2_font_m2icon_9_tf);
      u8g2.drawStr(0,11,flags);
      break;
    case 2:
      u8g2.setFont(u8g2_font_6x13_tr);
      u8g2.drawStr(38,13,"USB PWR MONITOR");
      u8g2.drawStr(0,25,"Lower Limit:");

      drawUMin();

      u8g2.setFont(u8g2_font_m2icon_9_tf);
      u8g2.drawStr(0,11,flags);
      break;
    case 3:
      u8g2.setFont(u8g2_font_6x13_tr);
      u8g2.drawStr(38,13,"USB PWR MONITOR");
      u8g2.drawStr(0,25,"Upper Limit:");

      drawUMax();

      u8g2.setFont(u8g2_font_m2icon_9_tf);
      u8g2.drawStr(0,11,flags);
      break;
  }
  
}

void getReadings(void) {
  #ifdef DEBUG
  Serial.print('.');
  #endif
  
  if(adc_u == 0) {
    adc_u = analogRead(ADC_U)*10;
  }else{
    adc_u = (adc_u + analogRead(ADC_U)*10) / 2;
  }
  
  if(adc_i == 0) {
    adc_i = analogRead(ADC_I)*10;
  }else{
    adc_i = (adc_i + analogRead(ADC_I)*10) / 2;
  }
  
  if(adc_DP == 0) {
    adc_DP = analogRead(ADC_DP)*10;
  }else{
    adc_DP = (adc_DP + analogRead(ADC_DP)*10) / 2;
  }
  
  if(adc_DN == 0) {
    adc_DN = analogRead(ADC_DN)*10;
  }else{
    adc_DN = (adc_DN + analogRead(ADC_DN)*10) / 2;
  }
  
  if(adc_VCC == 0) {
    adc_VCC = analogRead(ADC_VCC)*10;
  }else{
    adc_VCC = (adc_VCC + analogRead(ADC_VCC)) / 2;
  }
  
  if(adc_OV == 0) {
    adc_OV = analogRead(ADC_OV);
  }else{
    adc_OV = (adc_OV + analogRead(ADC_OV)*10) / 2;
  }
}

void checkVcc(void) {
  unsigned int vccchk = getVcc();

  if(vccchk <= BROWNOUT) {
    EEPROM.put(16, mAh);
    EEPROM.put(18, mWh);
    EEPROM.put(22, runtime);
    fetOff();
    digitalWrite(LED, HIGH);
    Serial.println(F("E:VCC"));
    Serial.flush();
    while(1) {}
  }
}

unsigned int getVcc(void) {
  unsigned int adco = (float)adc_VCC * ref_VCC / 10000;
  lastVcc = adco;
  adc_VCC = 0;
  return adco;
}

void procUART(void) {
  unsigned int temp=0;
  if(Serial.available()) {
    switch(Serial.read()) {
      case '1':
        fetOn();
        Serial.println(F("OK"));
        break;
      case '0':
        fetOff();
        Serial.println(F("OK"));
        break;
      case 'r':
        runtime = 0;
        mAh=0;
        mWh=0;
        mAh_c=0;
        mWh_c=0;
        uov=0;
        Serial.println(F("OK"));
        break;
      case 's':
        running = false;
        fetOff();
        Serial.println(F("OK"));
        break;
      case 'S':
        running = true;
        fetOn();
        Serial.println(F("OK"));
        break;
      case '<':
        temp = Serial.parseInt();
        if(temp > 0) {
          u_min = temp;
          EEPROM.put(0, u_min);
          Serial.println(F("OK"));
        }
        break;
        temp = Serial.parseInt();
        if(temp > 0) {
          u_max = temp;
          EEPROM.put(2, u_max);
          Serial.println(F("OK"));
        }
        break;
      case 'u':
        temp = Serial.parseInt();
        if(temp > 0) {
          ref_u = temp;
          EEPROM.put(4, ref_u);
          Serial.println(F("OK"));
        }
        break;
      case 'i':
        temp = Serial.parseInt();
        if(temp > 0) {
          ref_i = temp;
          EEPROM.put(6, ref_i);
          Serial.println(F("OK"));
        }
        break;
      case 'p':
        temp = Serial.parseInt();
        if(temp > 0) {
          ref_i = temp;
          EEPROM.put(8, ref_i);
          Serial.println(F("OK"));
        }
        break;
      case 'n':
        temp = Serial.parseInt();
        if(temp > 0) {
          ref_DN = temp;
          EEPROM.put(10, ref_DN);
          Serial.println(F("OK"));
        }
        break;
      case 'v':
        temp = Serial.parseInt();
        if(temp > 0) {
          ref_VCC = temp;
          EEPROM.put(12, ref_VCC);
          Serial.println(F("OK"));
        }
        break;
      case 'O':
        temp = Serial.parseInt();
        if(temp > 0) {
          ref_OV = temp;
          EEPROM.put(14, ref_OV);
          Serial.println(F("OK"));
        }
        break;
      case 'V':
        Serial.print(F("#Version: "));
        Serial.println(version);
        break;
      case 'm':
        uartBtn = 'm';
        break;
      case '+':
        uartBtn = '+';
        break;
      case '-':
        uartBtn = '-';
        break;
    }
  }
}

void procSwitch(void) {
  if(( lastkey+100) > millis()) return;
  
  if(lastkeyact) {
    if(digitalRead(SW) == HIGH && digitalRead(RE1) == HIGH && digitalRead(RE2) == HIGH) {
      lastkeyact = false;
      lastkey = millis()+50;
    }

    return;
  }
  
  if(digitalRead(SW) == LOW || uartBtn == 'm') {
    lastkeyact = true;
    lastkey = millis();

    if(menu == 2) {
      unsigned int temp=0;
      EEPROM.get(0, temp);

      if(temp != u_min) EEPROM.put(0, u_min);
    }
    if(menu == 3) {
      unsigned int temp=0;
      EEPROM.get(2, temp);

      if(temp != u_max) EEPROM.put(2, u_max);
    }
    
    menu++;
    if(menu > 3) menu = 0;
  }

  switch(menu) {
    case 0:
      if(digitalRead(RE1) == LOW || uartBtn == '+') {
        lastkeyact = true;
        lastkey = millis();
        if(running) {
          fetOff();
          running = false;
        }else{
          fetOn();
          uov=0;
          running = true;
        }
      }
      if(digitalRead(RE2) == LOW || uartBtn == '-') {
        lastkeyact = true;
        lastkey = millis();
        runtime = 0;
        mAh=0;
        mWh=0;
        mAh_c=0;
        mWh_c=0;
        uov=0;
      }
      break;
    case 1:
      break;
    case 2:
      if(digitalRead(RE1) == LOW || uartBtn == '+') {
        lastkeyact = true;
        lastkey = millis();
        u_min++;
      }
      if(digitalRead(RE2) == LOW || uartBtn == '-') {
        lastkeyact = true;
        lastkey = millis();
        u_min--;
      }
      break; 
    case 3:
      if(digitalRead(RE1) == LOW || uartBtn == '+') {
        lastkeyact = true;
        lastkey = millis();
        u_max++;
      }
      if(digitalRead(RE2) == LOW || uartBtn == '-') {
        lastkeyact = true;
        lastkey = millis();
        u_max--;
      }
      break;
  }
  uartBtn = 0x00;
}

unsigned int procVolt(void) {
  unsigned int adco = (float)adc_u * ref_u / 10000;

  if(adco > 620) { //use secondary ADC
    adco = (float)adc_OV * ref_OV / 1000;
  }

  adc_u=0;
  adc_OV=0; 
  
  return adco;
}

signed int procAmp(void) {
  signed int adco=0;

  
  
  adco = (((signed long)adc_i * ref_i) - ((signed long)ref_i_o*10000)) * ((float)ref_i_mva/100000);
  /*adco = adco - ref_i_o;
  adco *= ref_i_mva;
  adco /= 10;*/

  adc_i = 0;
  
  if(!output) return 0;
  return adco;
}

void procmAh(unsigned int timedelta) {
  boolean neg = false;
  signed int tamp = amp;

  if(tamp < 0) {
    tamp *= -1;
    neg = true;
    mAh_c = 0;
  }
  
  signed long temp = mAh_c;

  temp += (signed long)(tamp * 10 * timedelta) / 36;

  if(neg) {
    mAh -= (temp/100);
  }else{
    mAh += (temp/100);
    mAh_c = temp % 100;
  }
}

void procmWh(unsigned int timedelta) {
  signed long temp = mWh_c;
  temp += (((signed long)amp * timedelta * volt) / 3600);
  mWh_c = temp % 10;
  mWh += (temp/10);
}

void procDP(void) {
  DP = (float)adc_DP * ref_DP / 10000;
  adc_DP = 0;
}

void procDN(void) {
  DN = (float)adc_DN * ref_DN / 10000;
  adc_DN = 0;
}

void procSignaling(void) {
  if(DP > 180 && DP < 220 && DN > 180 && DN < 220) {
    signaling = 2; //Apple 0.5A
  }else if(DP > 180 && DP < 220 && DN > 260 && DN < 300) {
    signaling = 3; //Apple 1.0A
  }else if(DP > 260 && DP < 300 && DN > 180 && DN < 220) {
    signaling = 4; //Apple 2.0A
  }else{ //Check if pins are shorted for DCP
    digitalWrite(ADC_DP, LOW);
    pinMode(ADC_DP, OUTPUT);
    delay(2);
    if(analogRead(ADC_DN) > 16) {
      signaling = 1; //Nope - looks like something else is pulling it HIGH, propably data
    } else{
      pinMode(ADC_DP, INPUT_PULLUP);
      delay(2);
      if(analogRead(ADC_DN) > 16) {
        signaling = 0; //Nothing changed - propably not connected
      } else{
        signaling = 5; //Looks like DCP
      }
    }
    digitalWrite(ADC_DP, LOW);
    pinMode(ADC_DP, INPUT);
  }
}

void drawVolt(void) {
  String out;

  unsigned int adc = volt;

  if(uov==0) {
    if(adc < u_min) {
      Serial.println("UV");
      uov=1;
      fetOff();
      running = false;
    }
    if(adc > u_max) {
      Serial.println("OV");
      uov=2;
      fetOff();
      running = false;
    }
  }

  out =  "U: ";
  out += adc/100;
  out += '.';
  adc %= 100;
  if(adc < 10) out += '0';
  out += adc;
  out += "V";

  char outc[out.length()+1];
  out.toCharArray(outc, sizeof(outc));

  u8g2.drawStr(0,25,outc);
}

void drawAmp(void) {
  String out;

  signed int adc = amp;

  out =  "I: ";
  if(adc < 0) {
    out += '-';
    adc *= -1;
  }
  out += adc/100;
  out += '.';
  adc %= 100;
  if(adc < 10) out += '0';
  out += adc;
  out += "A";

  char outc[out.length()+1];
  out.toCharArray(outc, sizeof(outc));

  u8g2.drawStr(64,25,outc);
}

void drawWatt() {
  String out;

  signed int adc = (signed long)((signed long)volt * (signed long)amp) / 100;

  out =  "P: ";
  
  if(adc < 0) {
    out += '-';
    adc *= -1;
  }
  
  out += adc/100;
  out += '.';
  adc %= 100;
  if(adc < 10) out += '0';
  out += adc;
  out += "W";

  char outc[out.length()+1];
  out.toCharArray(outc, sizeof(outc));

  u8g2.drawStr(0,37,outc);
}

void drawAh(void) {
  String out = "";

  signed int adc = mAh;

  if(adc<0) {
    out += '-';
    adc*=-1;
  }

  out += adc/1000;
  out += '.';
  adc %= 1000;
  if(adc < 100) out += '0';
  if(adc < 10) out += '0';
  out += adc;
  out += "Ah";

  char outc[out.length()+1];
  out.toCharArray(outc, sizeof(outc));

  u8g2.drawStr(0,50,outc);
}

void drawWh(void) {
  String out = "";

  signed int adc = mWh;

  if(adc<0) {
    out += '-';
    adc*=-1;
  }

  out += adc/1000;
  out += '.';
  adc %= 1000;
  if(adc < 100) out += '0';
  if(adc < 10) out += '0';
  out += adc;
  out += "Wh";

  char outc[out.length()+1];
  out.toCharArray(outc, sizeof(outc));

  u8g2.drawStr(64,50,outc);
}

void drawTime(unsigned int calctime) {
  String out;

  int days = calctime / 86400;
  calctime %= 86400;

  int hours = calctime / 3600;
  calctime %= 3600;

  int minutes = calctime / 60;
  calctime %= 60;

  out  = days;
  out += "d ";
  out += hours;
  out += "h ";
  out += minutes;
  out += "m ";
  out += calctime;
  out += "s";

  char outc[out.length()+1];
  out.toCharArray(outc, sizeof(outc));

  u8g2.drawStr(0,63,outc);
}

void drawDP(void) {
  String out;

  unsigned int adc = DP;

  out =  "D+: ";
  out += adc/100;
  out += '.';
  adc %= 100;
  if(adc < 10) out += '0';
  out += adc;
  out += "V";

  char outc[out.length()+1];
  out.toCharArray(outc, sizeof(outc));

  u8g2.drawStr(0,25,outc);
}

void drawDN(void) {
  String out;

  unsigned int adc = DN;

  out =  "D-: ";
  out += adc/100;
  out += '.';
  adc %= 100;
  if(adc < 10) out += '0';
  out += adc;
  out += "V";

  char outc[out.length()+1];
  out.toCharArray(outc, sizeof(outc));

  u8g2.drawStr(64,25,outc);
}

void drawSignaling(void) {
  String out;

  switch(signaling) {
    case 0:
      out = "Not connected";
      break;
    case 1:
      out = "Data Connection";
      break;
    case 2:
      out = "Apple 0.5A";
      break;
    case 3:
      out = "Apple 1.0A";
      break;
    case 4:
      out = "Apple 2.0A";
      break;
    case 5:
      out = "USB Charger";
      break;
    default:
      out = "Unknown";
  }

  char outc[out.length()+1];
  out.toCharArray(outc, sizeof(outc));

  u8g2.drawStr(0,37,outc);
}

void drawVCC(void) {
  String out;

  unsigned int adc = lastVcc;

  out =  "Vcc: ";
  out += adc/100;
  out += '.';
  adc %= 100;
  if(adc < 10) out += '0';
  out += adc;
  out += "V";

  char outc[out.length()+1];
  out.toCharArray(outc, sizeof(outc));

  u8g2.drawStr(0,63,outc);
}

void drawUMin(void) {
  String out;

  unsigned int adc = u_min;

  out =  "Umin: ";
  out += adc/100;
  out += '.';
  adc %= 100;
  if(adc < 10) out += '0';
  out += adc;
  out += "V";

  char outc[out.length()+1];
  out.toCharArray(outc, sizeof(outc));

  u8g2.drawStr(0,50,outc);
}

void drawUMax(void) {
  String out;

  unsigned int adc = u_max;

  out =  "Umax: ";
  out += adc/100;
  out += '.';
  adc %= 100;
  if(adc < 10) out += '0';
  out += adc;
  out += "V";

  char outc[out.length()+1];
  out.toCharArray(outc, sizeof(outc));

  u8g2.drawStr(0,50,outc);
}

void fetOff(void) {
  output = false;
  digitalWrite(FET, LOW);
}

void fetOn(void) {
  output = true;
  digitalWrite(FET, HIGH);
}


 

BitBastelei #222 – USB Power Monitor – Hardware-Überlegungen

BitBastelei #222 - USB Power Monitor - Hardware-Überlegungen

(151 MB) 00:18:22

2016-12-11 11:00 🛈

Den USB Charger-Doctor und seine Gefährten dürften die meisten von euch kennen. Die kleinen Geräte können Spannung und Strom eines USB-Anschlusses messen und anzeigen. Leider fehlen mir ein paar Funktionen wie z.B. ein PC-Anschluss um die Daten aufzeichnen zu können. Also: Bauen wir uns selbst einen.

Ergänzungen:

Einem aktuellen Video von Hugatry’s HackVlog nach sollte sich auch Qualcomm Quick Charge erkennen lassen (EN):
https://www.youtube.com/watch?v=UYRZ0t5eyjE

Etwa zeitgleich hat auch Great Scott Labs ein ähnliches Gerät gebaut. Er nutzt statt einer PC-Anbindung eine SD-Karte zum aufzeichnen (EN):
https://www.youtube.com/watch?v=lrugreN2K4w

BitBasics OLED: Unterschiede & Ansteuerung mit Arduino

BitBasics OLED: Unterschiede & Ansteuerung mit Arduino

(255 MB) 00:25:41

2016-12-04 11:00 🛈

OLEDs werden in letzter Zeit auch bei vielen Bastlern immer beliebter. Statt einer Pixelmatrix mit Flüssigkristallen und externer Beleuchtung sorgen hier organische Komponenten für selbstleuchtende Bildpunkte. Durch die Technologie erreichen sie einen hohen Kontrast und sind auch draußen gut lesbar. Wer sich nicht durch die geringe Lebensdauer abschrecken lässt wird meist bei einem der zahlreichen 0.96″-Modulen mit 124×64 Pixeln und SSD1306-Controller landen. Mit diesen muss man sich nicht mit den zahlreichen Pins des Displays abmühen, sondern erhält einen fertigen Datenanschluss wie z.B. I²C.
Für die Ansteuerung unter Arduino muss man sich dabei nicht erst in das Datenblatt des OLED-Controllers einlesen, sondern kann auf eine der zahlreichen Libraries zurückgreifen. Die vermutlich bekannteste ist U8G2, Nachfolger der beliebten U8GLib. Mit diesen lassen sich Texte und Grafiken mit nur wenig Zeilen ausgeben.

BitBastelei #190 – ESP8266 & AMS2302 WLAN-Temperatur- und Feuchtesensor

BitBastelei #190 - ESP8266 & AMS2302 WLAN-Temperatur- und Feuchtesensor

(113 MB) 00:31:40

2016-03-27 10:00 🛈

Vor etwa einem Jahr hatte ich als Beispiel schon mal einen DHT22/AMS2302 Temperatur- und Feuchtesensor mit dem ESP8266 verbunden. Seinerzeit recht ineffizient mit fertiger Firmware. Da ich für einen Serverraum kurzfristig ein Monitoring brauche legen wir das Ganze nochmal neu auf – diesmal mit eigener Firmware, welche die Daten direkt an Volkszähler oder einen anderen Dienst sendet und zwischen den Messungen stromsparend in den Schlafmodus geht. Leider ist bei dem hier verwendeten ESP-01 eine Hardwaremodifikation nötig um Deep-Sleep zu ermöglichen.

Zeitmarken

  • 00:00 Aufbauplanung
  • 04:54 Deep-Sleep-Modifikation
  • 06:22 Software
  • 19:01 Flashen & ESP01-Stromverbrauch
  • 23:53 Vom Breadboard zum Streifenraster / 3.3-Regler
  • 29:15 Fazit

Links zum Thema

BitBastelei #190 – ESP8266 & AMS2302 WLAN-Temperatur- und Feuchtesensor weiterlesen