HC-SR04 (Ultraschall-Entfernungssensoren) an Arduino

Die HC-SR04 Ultraschallsensoren sind günstige Sensoren zur Erfassung von Distanzen per Ultraschall (woher sonnst kommt der Name). Kostenmäßig liegen diese bei etwa 4-5 EUR wenn man Sie in Deutchland kauft, bezieht man diese aus China, so liegt man bei etwa 1 EUR.

HC – SR04

Technische Daten

  • Betriebsspannung: DC 5V
  • Stromverbrauch: ~2mA
  • Sensorwinkel: <15°
  • Detektionsbereich: 2cm – 450cm
  • Präzision: 0,3cm

Anschlüsse und Verwendung

Pins:
1. VCC (5V)
2. trig (T)
3. echo (R)
4. GND

Die Grundsätzliche Funktionsweise ist wie folgt. Es muss ein Impuls auf dem Triggerpin gelegt werden, und auf dem Echo-Pin gibt es dann den Rechtecksignal, welches Proportional zur Distanz ist. Um sich Berechnung der Luafzeiten zu ersparen, gibt es zahlreiche Biliotheken. Ich selber habe die von Erik Simones verwendet https://github.com/ErickSimoes/Ultrasonic. Auf dieser Seite ist auch eine entsprechende Anleitung zu finden. In dieser Anleitung wird auch beschrieben, wie man die Bibliothek installiert.

In meinem Sketch habe ich 6 Ultraschall-Sensoren an den Arduino angeschlossen (mehr DIO-Pins habe ich beim Arduino-Nano nicht zur Verfügung gehabt).

#include <Ultrasonic.h>

Ultrasonic ultrasonic[6] = 
{
  Ultrasonic(3, 2),
  Ultrasonic(5, 4),
  Ultrasonic(7, 6),
  Ultrasonic(9, 8),
  Ultrasonic(11, 10),
  Ultrasonic(13, 12)
};
  
void setup() {
  Serial.begin(9600);

}

void loop() {
  for (int n=0; n<6; n++)
  {
    Serial.print("Sensor[");
    Serial.print(n);
    Serial.print("]: ");

    Serial.print(ultrasonic[n].read(CM)); // Prints the distance on the default unit (centimeters)
    Serial.println("cm");
  }
  delay(100);

}

DHT22 an ESP8622 + MQTT

Der DHT22 ist ein günstiger Sensor zur Messung der Temperatur und der Luftfeuchte. Dieser ist baugleich zum AM2302.
Der Sensor kann sowohl mit 3.3V als auch mit 5V betrieben werden. Also Ideal für gängige Microcontrollerplattformen wie Arduino, Rapsberry Pi, STM32 und weitere.
Der Anschluss ist wirklich simpel, Spannung, Masse und Signal. Der Datenaustausch erfolgt über einen Single-Bus, als seriell.

Technische Daten:

  • Digital Temperatur und Luftfeuchtigkeit ermitteln
  • DHT22 / AM2302
  • Betriebsspannung: DC 3.3-5.5V
  • Luftfeuchtigkeitsmessbereich : 0 bis 100% relative Luftfeuchte
  • Feuchtemessgenauigkeit: ±2% RH
  • Temperaturbereich: -40 bis +80 C
  • Temperaturmessgenauigkeit ±0.5
  • Single-Bus – Digitalsignalausgang, bidirektionale serielle Daten
  • Maße: 28mm x 12mm x 10mm

In meinem Beispiel habe ich den DHT22 an den ESP3266 angeschlossen. Dazu habe ich VCC and 3.3V angeschlossen, GND an GND und Data an den Pin D6 des Microcontrollers.

Im Endeffekt wird der DHT22 ausgelesen und die Werte an das Display geschrieben. Zusätzlich werden die Informationen per MQTT übertragen.
Das passende Codesnippet sieht wie folgt aus

/***************************************************
  This code uses the ESP8266 Kit8 with the following functionality
  @li [in] DHT22
  @li [out] some information at the display by I2C
  @li [out] MQTT
  @author Andreas Amann (quick and dirty)
 ****************************************************/
#include <ESP8266WiFi.h>
#include "Adafruit_MQTT.h"
#include "Adafruit_MQTT_Client.h"

/*************************  Display stuff *********************************/
#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_128X32_UNIVISION_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ 16, /* clock=*/ 5, /* data=*/ 4);

/*************************  DHT22 *********************************/
#include "DHT.h"

#define DHTPIN 12     // Digital pin connected to the DHT sensor
// Feather HUZZAH ESP8266 note: use pins 3, 4, 5, 12, 13 or 14 --
// Pin 15 can work but DHT must be disconnected during program upload.

//#define DHTTYPE DHT11   // DHT 11
#define DHTTYPE DHT22   // DHT 22  (AM2302), AM2321
//#define DHTTYPE DHT21   // DHT 21 (AM2301)

// Initialize DHT sensor.
// Note that older versions of this library took an optional third parameter to
// tweak the timings for faster processors.  This parameter is no longer needed
// as the current DHT reading algorithm adjusts itself to work on faster procs.
DHT dht(DHTPIN, DHTTYPE);

char strTmp[8]; // Buffer big enough for 7-character float

/************************* WiFi Access Point *********************************/
#define WLAN_SSID       "MYSSID"
#define WLAN_PASS       "123412341234"

/************************* Adafruit.io Setup *********************************/
#define AIO_SERVER      "192.168.180.101"
#define AIO_SERVERPORT  1883                   // use 8883 for SSL
#define AIO_USERNAME ""
#define AIO_KEY ""
//#define AIO_USERNAME    "...your AIO username (see https://accounts.adafruit.com)..."
//#define AIO_KEY         "...your AIO key..."

/************ Global State (you don't need to change this!) ******************/
// Create an ESP8266 WiFiClient class to connect to the MQTT server.
WiFiClient client;
// or... use WiFiFlientSecure for SSL
//WiFiClientSecure client;

// Setup the MQTT client class by passing in the WiFi client and MQTT server and login details.
// Notice MQTT paths for AIO follow the form: <username>/feeds/<feedname>
Adafruit_MQTT_Client mqtt(&client, AIO_SERVER, AIO_SERVERPORT, AIO_USERNAME, AIO_KEY);
Adafruit_MQTT_Publish pub_humidity = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/uc/humidity");
Adafruit_MQTT_Publish pub_temperature = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/uc/temp");

/*************************** Sketch Code ************************************/
void MQTT_connect();

/****************************************************************************/
void setup() 
{
  Serial.begin(115200);
  delay(10);

  Serial.println(F("Adafruit MQTT demo"));

  // Connect to WiFi access point.
  Serial.println(); 
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(WLAN_SSID);

  WiFi.begin(WLAN_SSID, WLAN_PASS);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }
  Serial.println();
  Serial.println("WiFi connected");
  Serial.println("IP address: "); Serial.println(WiFi.localIP());

  // init display
  u8g2.begin();
  
  // init sensor
  dht.begin();

  // sendout message
  Serial.println(F("DHTxx test!"));
}

/************ ugly global variable *************************************/
uint32_t x=0;

/************** read out humidity and log messages ********************/
float GetHumidity()
{
  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  float h = dht.readHumidity();

  // Check if any reads failed and exit early (to try again).
  if (isnan(h)) 
  {
    Serial.println(F("Failed to read from DHT sensor!"));
  }

  return h;
}

/************ read out temperatur and log messages *********************/
float GetTemperature()
{
  // Read temperature as Celsius (the default)
  float t = dht.readTemperature();

  // Check if any reads failed and exit early (to try again).
  if (isnan(t)) {
    Serial.println(F("Failed to read from DHT sensor!"));
  }

  return t;
}

/************** display provided values ***************************/
void DisplayValues(float t, float h)
{
   // printout to display
  u8g2.clearBuffer();          // clear the internal memory
  u8g2.setFont(u8g2_font_ncenB08_tr); // choose a suitable font
  u8g2.drawStr(0,10,"Humidity [%]: ");  // write something to the internal memory
  dtostrf(h, 6, 2, strTmp); // Leave room for too large numbers!
  u8g2.drawStr(90,10,strTmp);  // write something to the internal memory
  
  u8g2.drawStr(0,25,"Temperature [C°]: ");  // write something to the internal memory
  dtostrf(t, 6, 2, strTmp); // Leave room for too large numbers!
  u8g2.drawStr(90,25,strTmp);  // write something to the internal memory
  //u8g2.drawStr(0,31,"Heat index");  // write something to the internal memory
  u8g2.sendBuffer();          // transfer internal memory to the display
}

/******** send out data by MQTT *********************************/
void PublishTemperature(float t)
{
  if (! pub_temperature.publish(t)) 
  {
    Serial.println(F("Failed(__LINE__)"));
  } 
}

/******** send out data by MQTT *********************************/
void PublishHumidity(float h)
{
  if (! pub_humidity.publish(h)) 
  {
    Serial.println(F("Failed(__LINE__)"));
  } 
}

/************ loop **********************************************/
void loop() 
{
  // Ensure the connection to the MQTT server is alive (this will make the first
  // connection and automatically reconnect when disconnected).  See the MQTT_connect
  // function definition further below.
  MQTT_connect();

 const float t = GetTemperature();
 const float h = GetHumidity();
 PublishTemperature(t);
 PublishHumidity(h);
 DisplayValues(t,h);

  // ping the server to keep the mqtt connection alive
  // NOT required if you are publishing once every KEEPALIVE seconds
  /*
  if(! mqtt.ping()) {
    mqtt.disconnect();
  }
  */
}

// Function to connect and reconnect as necessary to the MQTT server.
// Should be called in the loop function and it will take care if connecting.
void MQTT_connect() 
{
  int8_t ret;

  // Stop if already connected.
  if (mqtt.connected()) 
  {
    return;
  }

  Serial.print("Connecting to MQTT... ");

  uint8_t retries = 3;
  while ((ret = mqtt.connect()) != 0) { // connect will return 0 for connected
       Serial.println(mqtt.connectErrorString(ret));
       Serial.println("Retrying MQTT connection in 5 seconds...");
       mqtt.disconnect();
       delay(5000);  // wait 5 seconds
       retries--;
       if (retries == 0) {
         // basically die and wait for WDT to reset me
         while (1);
       }
  }
  Serial.println("MQTT Connected!");
}

Heltec WiFi Kit 8 (ESP8266) mit Arduino IDE programmieren

Das Heltec WiFi Kit 8 ist ein kostengünstiges Entwicklungsboard, das mit der Arduino-IDE benutzt werden kann. Es besitzt folgende Eigenschaften:

  • ESP8266 (160MHz Tensilica L06 32-bits,SRAM, Wi-Fi)
  • UART x 2; SPI x 1; I2C x 1; I2S x 1
  • 10 – bits ADC
  • 17 general GPIO
  • 0.91″ 128*32 OLED display
  • 4MB(32M-bits) SPI FLASH

Um das Modul mit der Arduino IDE benutzen zu können, sind folgende Einstellungen notwendig:

Es gibt noch einen wichtigen Punkt zu beachten. Anscheinend gibt es wohl zwei verschiedene Versionen dieses Boards. Über folgende Links habe ich diverse zusätzliche Informationen erhalten:

  • https://github.com/Heltec-Aaron-Lee/WiFi_Kit_series
  • http://stefanfrings.de/esp8266/
  • https://robotzero.one/heltec-wifi-kit-8/

Hilscher NetIO für Hausautomatisierung

Vor geraumer Zeit hatte ich einen Hilscher NetIO für die Hausautomatisierung beschafft. Jetzt endlich bin ich dazu gekommen, diesen in Betrieb zu nehmen. Aber fangen wir erst mit den Daten & Fakten an.

Das Gerät hat folgende technische Eigenschaften (entnommen der Herstellerseite):

  • Betriebsspannung 24V +-6V (DC)
  • 4 Kern 64bit ARM BCM2837
  • 1GB DDR3 RAM
  • 8GB industie MLC NAND Speicher
  • Stromverbrauch 170mA
  • Ethernet 10/100Mbit
  • 2 Sockets für Profinet / Ethercat ( Hilscher netx 51)
  • Wifi
  • Bluetooth
  • HDMI
  • Metallgehäuse
  • DIN-SChienenanschluss (Schaltschrank)

Also wie ihr seht, ist es quasi ein Raspberry-Pi 3 nur in Industrietauglicher Ausführung. Der Spaß kostet bei Amazon etwa 300 EUR. Jetzt muss jeder für sich selsbt entscheiden, ob einem das Wert ist.

Als Betriebssystem kommt ein Linux (out of the Box) zum Einsatz. Auf dem Device gibt es graphisches Frontend, welches einem die Konfiguration übernimmt. Der eigentlicehn Konsolen-Zugriff ist eigentlich nicht vorgesehen. Alle Softwareinstallationen erfolgen über Docker (also eigene getrennte Container).

Inbetriebnahme Dopplerradar OPS243

Im Zuge eines neuen Projektes wurde ein Dopplerradar der Firma OmniPreSense mit der Bezeichnung OPS243 angeschafft.
Technisch ist das hochinteresannt:

  • Detektionsbereich 1-100m
  • Geschwindigkeitsdetektion bis zu 348 mph
  • Richtungserkennung ( kommend oder gehend)

Weitere Informationen sind hier zu finden: https://omnipresense.com/product/ops243-doppler-radar-sensor/

Standardmäßig sendet der Sensor seine Daten per serielles Interface heraus. Mit folgenden Einstellungen, lassen sich die Daten abzapfen:

/dev/ttyACM0  9600 8N1

Folgender Datenstrom ergibt sich:

Die Ausgabestream gibt die Detektierten Objekte in m/2 an.

Nachdem dies nun zu funktionieren scheint, gilt es die Integration ins ROS zu vollziehen. Hierbei gehe zu http://wiki.ros.org/radar_omnipresense und folge der Installationsanweisung. Ich installiere das fehlende ROS Paket mit

sudo apt install ros-kinetic-radar-omnipresense

und nun kommt dier Erkenntnis, dass ich keine out of the Box-Visualisierung habe. Ich muss mich um was spezielles wohl kümmern.

Linux / UNIX minicom

Unter Linux hat man die Möglichkeit mit zahlreichen Tools auf die serielle Schnittstelle zuzugreifen. Wenn mir eine GUI zur Verfügung steht, so nutze ich am liebsten putty, da ich dieses Werkzeug auch unter Windows benutze, bin ich damit sehr vertraut. Jedoch habe ich nicht immer die Möglichkeit mit einer GUI zu arbeiten, oder wenn mal schnell besondere Rechte für den Konsolen-Zugriff benötigt werden, ist es auf der Shell einfacher

Mein Lieblingswerkezug hierfür ist dann minicom. minicom bietet alles was das Herz begehrt, ohne konkret darauf einzugehen.

Installieren von minicom

Unter Debian / Ubuntu lässt sich minicom mit folgenden Befehl installieren:

sudo apt-get install minicom

Benutzen von minicom

Bevor man minicom benutzen kann, muss es konfiguriert werden. Hierzu startet man minicom mit folgenden Parameter:

minicom -s

Möchte man stattdessen ein “buntes” minicom haben, so fügt man zusätzlich noch -c on der Parameterliste hinzu:

minicom -s -c on

Wenn ihr dauerhaft irgendwelche Parameter minicom mitgeben wollt, so könnt ihr gerne die MINICOM Umgebungsvariable überschreiben bzw. setzen ( minicom sucht nach dieser Variablen, Kommandozeilenparameter sind dominant)

export MINICOM="-c on"

Und so sieht jetzt mein minicom aus, wenn ich die Daten des Dopplerradars (OPS243) via seriellem Interface (/dev/ttyACM0) auslese

RPLidar A3 Inbetriebnahme unter ROS kinetic

Für ein aktuelles Projekt wird ein RPLidar A3 unter ROS benötigt. Von den Daten her ist er für ein Low-Budget Lidar ganz brauchbar:

  • Entfernung: 10-25m
  • Abtastrate: 16.000-10.000 Mal pro Sekunde
  • Abtastrate: 10-20 Hz
  • Winkelauflösung: 0,3375°, 0,54°
  • Unterstützt frühere SDK-Protokolle

Basierend auf der Anleitung unter https://blog.zhaw.ch/icclab/rplidar/ bin ich entsprechend ans Werk gegangen.

### init ros
sudo rosdep init
rosdep update
echo "source /opt/ros/kinetic/setup.bash" >> ~/.bashrc
source ~/.bashrc
sudo apt-get install python-rosinstall
### Create a ROS Workspace
mkdir -p ~/catkin_ws/src
cd ~/catkin_ws/src
catkin_init_workspace

Entgegen der ursprünglichen Anleitung habe ich ein anderes Repository genommen. Als Quelle diente mir die ROS-Webseite http://wiki.ros.org/rplidar_ros. Darin befindet

cd ~/catkin_ws/src
git clone https://github.com/Slamtec/rplidar_ros.git

Nun gilt es “alles” zu bauen und die Umgebungsvariablen zu setzen

### Build with catkin
cd ~/catkin_ws/
catkin_make

### Set environment when build is complete
source devel/setup.bash

Gestartet wird nun RViz mit dem entsprechenden Launcher

### Launch demo with rviz
roslaunch rplidar_ros view_rplidar.launch

Und so sieht es dann aus, wenn alles funktioniert:

Welche Probleme sind mit während der Inbetriebnahme entstanden

  • Zugriffsrechte auf das /dev/ttyUSB0 device waren fehlerhaft. Hier gibt es verschiedene Möglichkeiten. Bitte daran denken, nach dem Ändern der Gruppenberechtigungen, einmal ausloggen und neu einloggen!
    • den eigenen Benutzer in die dialout-gruppe hinzuzufügen, durch modifizieren der Datei /etc/group.
    • oder mit Hilfe des Folgenden Befehls
      sudo gpasswd –add ${USER} dialout
  • Standardmäßig ist die /dev/ttyUSB0 auf 115000Baud eingestellt, dies Funktioniert auch für den A1 und A2. Da ich aber den A3 hatte, musste dies auf 256000Baudumgestellt werden. Dazu habe ich folgende Datei verändert:
    nano ~/catkin_ws/src/rplidar_ros/launch/rplidar.launch
    Die Zeile mit den 115000 habe ich entfernt und die 256000 Zeile entsprechend hereingenommen.

Und wie ich nun am Ende mitbekommen habe, gibt es auch ein entsprechendes ROS paket, welches ich installiere.

Debian/Ubuntu: Probleme nach Repository-Namensänderung

Tritt nach einem z.B. Debian release im testing zweig ein Namenswechsel ein (z.B: von buster nach bullseye) so erscheint folgende Fehlermeldung:

Get:1 http://ftp.halifax.rwth-aachen.de/debian testing InRelease [117 kB]  Get:2 http://ftp.halifax.rwth-aachen.de/debian testing-updates     InRelease [38.8 kB]                     
Hit:3 http://packages.ros.org/ros/ubuntu buster InRelease
Reading package lists... Done 
E: Repository 'http://ftp.halifax.rwth-aachen.de/debian  testing InRelease' changed its 'Codename' value from 'buster' to        'bullseye'       
N: This must be accepted explicitly before  updates for this       repository can be applied. See apt-secure(8) manpage for details.  

Dies kann ganz einfach vollzogen werden, wenn statt

apt-get

einfach

apt get

benutzt wird.

Lang’ lang’ ist’s her … aber die Welt ist nicht stehen geblieben

Seit den letzten Beiträgen ist vieles passiert. Sowohl privat als auch beruflich.

  • Zum einen bin ich 2017 Vater geworden.
  • Gegen Ende 2017 wurde ein neues Unternehmen namens AXON Innovations (https://axon-innovations.com) gegründet.
  • Ebenfalls im Herbst / Winter 2017 haben wir unser Haus in Leipzig gekauft.
  • Das Jahr 2018 war von Ende Januar bis Anfang Dezember von der Kernsanierung des Objektes gekennzeichnet.
  • Mitte 2018 habe ich dann eine Tochter meiner Firma im Ausland gegründet.

Und nebenbei rufen immer die Pflichten als Famlienvater einerseits aber auch in meinen Rollen in den verschiedenen Firmen. So dass es folglich hier sehr ruhig wurde. Ich möchte versuchen, die fehlende Zeit entsprechend nachzutragen, aber auch dies wird entsprechend Zeit benötigen.

Runter mit der Tapete

Als wir das Haus bekommen haben, sah es wie folgt aus:

Uns war klar, die Tapete muss raus, also sind wir voller Elan ins Haus gestürmt, und haben das “gelumpe” entfernt. In Summe haben wir 100 Stunden gebraucht, um das komplette haus, und die Decken tapetenfrei zu bekommen …

Tja, irgendwann waren wir fertig, bei dieser Gelegenheit haben wir auch gleich “ein paar” Fliesen entfernt. Es kam aber schnell die Erkenntnis, dass ein 1kg schwerer Kress-Bohrhammer nicht viel Bums hat. Und das Tepeten entfernen eine scheiß Arbeit ist.

Was besonders war, ist dass jeder Raum eine andere Putzfarbe hatte 🙂