Les broches SDA et SCl n’étant pas accessibles simplement, elle sont redéfinies sur GP0 et GP1 (respectivemenent PCB pins 3 et 4).
L’tilisation d’autre PINs reste possible mais les PINs recommendées sont 0, 1, 2, 3, 14, 20, 21, 22, 23, ls autres étant utilisées par BOOT, JTAG, FLASH … et donc posent problèmes.
ESP32S WROOM 30 pins | AHT20-BMP280 |
---|---|
GPIO/D 1 | SDA |
GPIO/D 0 | SCL |
GND | GND |
3.3 Volts |
ATTENTION: les PINs SDA et SCL ont abolument besoin d’une résistance de PullUp (entre 4.7 et 10 kohms) qui les raccordent au +3,3 volts, sans cela, le bus sera instable lors des transitions d’état.
Le firmware de l’ESP-C6 est écrit sur base de la bibliothèque zigbee (Arduino IDE core).
Connexion sur une instance zigbee2mqtt.
Les données de Température et humidité sont bien reçues et envoyée sur le boker mqtt.
#include "config.h"
AHT20 aht;
Adafruit_BMP280 bmp;
extern Stream *console;
extern volatile int count;
int previous=0;
ZigbeeTempSensor zbTempSensor = ZigbeeTempSensor(TEMP_SENSOR_ENDPOINT_NUMBER);
ZigbeePressureSensor zbPressureSensor = ZigbeePressureSensor(PRESSURE_SENSOR_ENDPOINT_NUMBER);
//ZigbeeWindSpeedSensor zbWindSpeedSensor = ZigbeeWindSpeedSensor(WIND_SPEED_SENSOR_ENDPOINT_NUMBER);
ZigbeeAnalog zbAnalogDevice = ZigbeeAnalog(ANALOG_DEVICE_ENDPOINT_NUMBER);
ZigbeeAnalog zbWindSpeedSensor = ZigbeeAnalog(WIND_SPEED_SENSOR_ENDPOINT_NUMBER);
uint8_t button = BOOT_PIN;
unsigned long windinstant_t=0;
unsigned long wind_avg_t=0;
void setup() {
Serial.begin(115200);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}
console = &Serial;
pinMode(button, INPUT_PULLUP);
Wire.begin(SDA,SCL);
Serial.println("\nI2C Scanner");
scanDevices(&Wire);
if (aht.begin() == false) {
console->println("AHT20 not detected");
} else {
console->println("Found AHT20");
}
bmp.begin(0x77);
setwind();
zbTempSensor.setManufacturerAndModel("ON4KCH", "ZigbeeMeteoStation");
zbTempSensor.addOTAClient(OTA_UPGRADE_RUNNING_FILE_VERSION, OTA_UPGRADE_DOWNLOADED_FILE_VERSION, OTA_UPGRADE_HW_VERSION);
zbTempSensor.setMinMaxValue(10, 50);
zbTempSensor.setTolerance(1);
zbTempSensor.addHumiditySensor(0, 100, 1);
// Optional: Time cluster configuration (default params, as this device will revieve time from coordinator)
zbTempSensor.addTimeCluster();
//zbPressureSensor.setMinMaxValue(0, 10000);
//zbPressureSensor.setTolerance(1);
//zbPressureSensor.setReporting(0, 30, 1);
// Set up analog input
zbAnalogDevice.addAnalogInput();
// second analog input gust
zbWindSpeedSensor.addAnalogInput();
//zbAnalogDevice.setAnalogInputApplication(ESP_ZB_ZCL_AI_RPM_OTHER);
// Add endpoint to Zigbee Core
Zigbee.addEndpoint(&zbWindSpeedSensor);
// Add endpoint to Zigbee Core
Zigbee.addEndpoint(&zbTempSensor);
Zigbee.addEndpoint(&zbPressureSensor);
//Zigbee.addEndpoint(&zbWindSpeedSensor);
Zigbee.addEndpoint(&zbAnalogDevice);
Serial.println("Starting Zigbee...");
// When all EPs are registered, start Zigbee in End Device mode
if (!Zigbee.begin()) {
Serial.println("Zigbee failed to start!");
Serial.println("Rebooting...");
ESP.restart();
} else {
Serial.println("Zigbee started successfully!");
}
Serial.println("Connecting to network");
while (!Zigbee.connected()) {
Serial.print(".");
delay(100);
}
zbAnalogDevice.setAnalogInputReporting(0,30,0.1);
zbWindSpeedSensor.setAnalogInputReporting(0, 30, 10);
// Set reporting interval for windspeed measurement in seconds, must be called after Zigbee.begin()
// min_interval and max_interval in seconds, delta (WindSpeed change in m/s)
// if min = 1 and max = 0, reporting is sent only when windspeed changes by delta
// if min = 0 and max = 10, reporting is sent every 10 seconds or windspeed changes by delta
// if min = 0, max = 10 and delta = 0, reporting is sent every 10 seconds regardless of windspeed change
//zbWindSpeedSensor.setReporting(0, 20, 0);
// Start Zigbee OTA client query, first request is within a minute and the next requests are sent every hour automatically
zbTempSensor.requestOTAUpdate();
}
void mesure( measure &val) {
// Measure sensor values
thp(val);
// Update temperature and humidity values in Temperature sensor EP
zbTempSensor.setTemperature(val.temperature);
zbTempSensor.setHumidity(val.humidity);
zbPressureSensor.setPressure(int(val.pressure));
// Report temperature and humidity values
zbTempSensor.report();
Serial.printf("Reported temperature: %.2f°C, Humidity: %.2f%%\r\n", val.temperature, val.humidity);
zbPressureSensor.report();
Serial.printf("Reported pressure: %.2f°mBar\r\n", val.pressure);
zbAnalogDevice.setAnalogInput(val.avgspeed);
Serial.printf("Reported gust wind speed (km/hr): %6.2f\r\n", val.gust);
zbWindSpeedSensor.setAnalogInput(val.gust);
zbWindSpeedSensor.reportAnalogInput();
Serial.printf("Reported avg wind speed (km/hr): %6.2f\r\n", val.avgspeed);
zbAnalogDevice.reportAnalogInput();
// Add small delay to allow the data to be sent before going to sleep
delay(100);
}
void loop() {
if (digitalRead(button) == LOW) { // Push button pressed
// Key debounce handling
delay(100);
int startTime = millis();
while (digitalRead(button) == LOW) {
delay(50);
if ((millis() - startTime) > 10000) {
// If key pressed for more than 10secs, factory reset Zigbee and reboot
Serial.println("Resetting Zigbee to factory and rebooting in 1s.");
delay(1000);
// Optional set reset in factoryReset to false, to not restart device after erasing nvram, but set it to endless sleep manually instead
Zigbee.factoryReset(false);
Serial.println("Going to endless sleep, press RESET button or power off/on the device to wake up");
esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_TIMER);
esp_deep_sleep_start();
}
}
}
measure val;
int hits;
// take a measure from sensor and report to zigbee
mesure(val);
char retval[256];
windinstant_t = millis();
wind_avg_t = millis();
val.hitcnt=1; // # of interval for wind average calculation
while (true) {
unsigned long now = millis();
// compute instant speed over the WIND_INSTANT inerval
// store the result in val mesure structure
if ((now - windinstant_t) >= WIND_INSTANT ) {
console->print("Counted: ");
console->println(hits);
// calculate and store "instant speed"
val.speed = Speed();
float factor = float(val.hitcnt - 1)/val.hitcnt;
float temp = val.avgspeed * factor;
//sprintf(retval,"Interval: %d\tFactor %6.2f\tAVG*factor %6.2f\tlast speed %6.2f \tavg speed %6.2f\n", val.hitcnt, factor, temp, val.speed, val.avgspeed);
//console->println(retval);
val.avgspeed = temp + (val.speed / val.hitcnt);
zbAnalogDevice.setAnalogInput(val.avgspeed);
sprintf(retval,"Interval: %d\tlast speed %6.2f \tavg speed %6.2f\n", val.hitcnt, val.speed, val.avgspeed);
console->println(retval);
if (val.hitcnt >= 6) {
val.hitcnt = 1;
val.gust = val.speed;
} else {
val.hitcnt += 1;
if ( val.speed > val.gust ){
val.gust = val.speed;
}
}
previous = hits;
windinstant_t = now;
} else if ( (now - wind_avg_t) >= WIND_AVG) {
console->println("Value read from sensors");
mesure(val);
sprintf(retval,"AHT20 - Temp: %6.2f °C Humidity: %d %%\tBMP280 - Temp: %6.2f °C Pressure: %7.2f hPa\tlast speed %6.2f \tavg speed %6.2f\n",val.temperature, val.humidity,val.temperature2, val.pressure, val.speed, val.avgspeed);
console->println(retval);
wind_avg_t = now;
}
}
delay(10000);
}
#include "config.h"
Stream *console;
uint32_t deviceOnline = 0x00;
extern AHT20 aht;
extern Adafruit_BMP280 bmp;
volatile int count = 0;
const byte interruptPin = 3;
enum {
POWERMANAGE_ONLINE = _BV(0),
DISPLAY_ONLINE = _BV(1),
RADIO_ONLINE = _BV(2),
GPS_ONLINE = _BV(3),
PSRAM_ONLINE = _BV(4),
SDCARD_ONLINE = _BV(5),
AXDL345_ONLINE = _BV(6),
BME280_ONLINE = _BV(7),
BMP280_ONLINE = _BV(8),
BME680_ONLINE = _BV(9),
QMC6310_ONLINE = _BV(10),
QMI8658_ONLINE = _BV(11),
PCF8563_ONLINE = _BV(12),
OSC32768_ONLINE = _BV(13),
};
void IRAM_ATTR counter() {
static unsigned long last_micros = 0;
unsigned long interrupt_time = millis();
if ( interrupt_time - last_micros > 50UL ) {
count += 1; // increment count
}
last_micros = interrupt_time;
}
void scanDevices(TwoWire *w)
{
uint8_t err, addr;
int nDevices = 0;
uint32_t start = 0;
console->println("I2C Devices scanning");
for (addr = 1; addr < 127; addr++) {
start = millis();
w->beginTransmission(addr); delay(2);
err = w->endTransmission();
if (err == 0) {
nDevices++;
switch (addr) {
case 0x77:
case 0x76:
console->println("\tFind BMX280 Sensor!");
deviceOnline |= BME280_ONLINE;
break;
case 0x34:
console->println("\tFind AXP192/AXP2101 PMU!");
deviceOnline |= POWERMANAGE_ONLINE;
break;
case 0x3C:
console->println("\tFind SSD1306/SH1106 dispaly!");
deviceOnline |= DISPLAY_ONLINE;
break;
case 0x51:
console->println("\tFind PCF8563 RTC!");
deviceOnline |= PCF8563_ONLINE;
break;
case 0x1C:
console->println("\tFind QMC6310 MAG Sensor!");
deviceOnline |= QMC6310_ONLINE;
break;
default:
console->print("\tI2C device found at address 0x");
if (addr < 16) {
console->print("0");
}
console->print(addr, HEX);
console->println(" !");
break;
}
} else if (err == 4) {
console->print("Unknow error at address 0x");
if (addr < 16) {
console->print("0");
}
console->println(addr, HEX);
}
}
if (nDevices == 0)
console->println("No I2C devices found\n");
console->println("Scan devices done.");
console->println("\n");
}
void thp( measure &val){
/*
return a structure with measured values from the sensors
REQUIRES initialization of I2C devices:
AHT20 aht;
Adafruit_BMP280 bmp;
*/
val.temperature = aht.getTemperature();
val.humidity = aht.getHumidity();
val.pressure = bmp.readPressure() / 100.0;
val.temperature2=bmp.readTemperature();
val.hit= float(count);
}
float Speed() {
/*
calculate the linear speed from magnets hit count, the routine gets called when average timer lapse (thus after measureperiod ms).
REQUIRES:
count: number of magnet detection
measureperiod: averaging period for rotational counts (ms)
RADIUS= distance between HAL detector and rotation axis centre.
PRVIDES:
sets global variable float speed
*/
noInterrupts ();
int interval = WIND_INSTANT / 1000; //anemometer averaging interval (sec)
char text[128]; //text buffer for sprintf
int local = count;
float speed;
float RPM;
int tour = local / 4; //3 magnets, it takes 4 hits to detect a full 360°
//speed = 3.1415926 * 2 * float(tour) * RADIUS / float(interval) ;
RPM = float(local) * ( 60 / interval); // tour/minutes
speed = RPM * RADIUS * 60 * 3.1415926 * 2. / 1000.; // vitesse radiale km/hr = vitesse angulaire (rad/min) * 2 Pi * rayon (m) * 60 (min/hr) / 1000 (m/km)
if (local > 0) {
sprintf(text," Speed calculation: Count %d\tRPM %8.2f (T/min)\tspeed %8.4f (km/hr) ",local,RPM, speed);
console->println(text);
}
count=0;
interrupts ();
return speed;
}
void setwind(){
/* et the interrupt mechanism that intercept the magnet detection and accumulates its counting */
pinMode(interruptPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(interruptPin), counter, RISING);
//timermeasure.set(measureperiod, Speed);
//TTNuplink.set(ttnuplinkperiod, TTNsend);
}
#include <Wire.h>
#include <AHT20.h>
#include <Adafruit_BMP280.h>
#ifndef ZIGBEE_MODE_ED
#error "Zigbee end device mode is not selected in Tools->Zigbee mode"
#endif
#include "Zigbee.h"
/* Zigbee OTA configuration */
#define OTA_UPGRADE_RUNNING_FILE_VERSION 0x01010100 // Increment this value when the running image is updated
#define OTA_UPGRADE_DOWNLOADED_FILE_VERSION 0x01010101 // Increment this value when the downloaded image is updated
#define OTA_UPGRADE_HW_VERSION 0x0101 // The hardware version, this can be used to differentiate between different hardware versions
/* Zigbee temperature sensor configuration */
#define TEMP_SENSOR_ENDPOINT_NUMBER 10
#define PRESSURE_SENSOR_ENDPOINT_NUMBER 11
#define ANALOG_DEVICE_ENDPOINT_NUMBER 12
#define WIND_SPEED_SENSOR_ENDPOINT_NUMBER 9
#define RADIUS 0.028 // 28 mm de rayon
#define AVGINTERVALS 6 //# of intervale for average speed should be WIND_AVG / WIND_INSTATNT
#define WIND_INSTANT 5000UL //intervale to compute the instant speed 5000 ms
#define WIND_AVG 30000UL // reporting interval 30 sec
#define SCL 1
#define SDA 0
typedef struct {
float temperature;
float temperature2;
float pressure;
int humidity;
float hit;
float speed;
float gust;
int hitcnt; // number of intervals used in wind average calculation
float avgspeed; // average speed
}
measure;
void scanDevices(TwoWire *w);
void thp( measure &val);
void setwind();
void IRAM_ATTR counter();
float Speed();