SHT31 Sensor mit Attiny85 auslessen

Hallo liebes Forum,
vor kurzem habe ich mir SHT31 Sensoren besorgt die auch 1A Funktionieren (getestet mit ESP32) nun will ich diese mit einem Attiny85 auslessen und mit einem HC-12 Modul versenden, das Funktioniert allerdings nicht.

VCC-Attiny85 verbunden mit VCC-SHT31 sowie mit dem VCC-HC12
GND-Attiny85 verbunden mit GND-SHT31 sowie mit dem GND-HC12
SCL-SHT31 verbunden mit PB2-Attiny
SDA-SHT31 verbunden mit PB0-Attiny
RX-HC12 verbunden mit PB3-Attiny

Der test Sketch:

#include <Arduino.h>
#include <avr/wdt.h>
#include <avr/sleep.h>
#include <SoftwareSerial.h>
#include <Adafruit_SHT31.h>

constexpr byte SHT31_ADDR {0x44};
constexpr byte UNUSEDPINS[] {4};

SoftwareSerial hc12(4, 3);   // TX = 4, RX = 3
Adafruit_SHT31 sht31 = Adafruit_SHT31();

constexpr byte WATCHDOG_WAKEUPS_TARGET {37};   // 8 * 7 = 56 seconds between each data collection

// watchdog ISR
ISR(WDT_vect) 
{
  // nothing to do here, just wake up
}

void enableWatchdog() 
{
  cli();
  MCUSR &= ~(1 << WDRF);
  WDTCR |= (1 << WDCE) | (1 << WDE);
  WDTCR = 1 << WDP0 | 1 << WDP3;
  WDTCR |= (1 << WDIE);
  sei();
}

// function to go to sleep
void enterSleep(void) {
  ADCSRA &= ~(1 << ADEN);              // switch off ADC -320µA
  set_sleep_mode(SLEEP_MODE_PWR_DOWN); // SLEEP_MODE_PWR_DOWN for lowest power consumption. 
  sleep_enable();
  sleep_mode();
  sleep_disable();
}

void initADC0() {
  // Read 1.1V reference as input with reference operating voltage vcc
  // Reference Vcc and analog input = internal reference 1.1V

 // Initialise ADC with REFS[2:0] is 0 = VCC as Ref,  MUX[3:0] 1100 = Vbg as Input,
  ADMUX = _BV(MUX3) | _BV(MUX2);
  bitSet(ADCSRA, ADEN);   // Enable
  delay(100);              // Wait until the reference has stabilized
  
  // After activating the ADC, a "dummy readout" is recommended.
  // In other words, a value is read and discarded to allow the ADC to "warm up"
  ADCSRA |= _BV(ADSC);                 // Start conversion
  while ((ADCSRA & _BV(ADSC))) { ; }   // measure
  (void)ADCW;                          // Discard dummy readout..
}

constexpr uint16_t INTERN {1070};   // determined per IC
constexpr uint32_t INTERNxRESOLUTION {INTERN * 1024UL};

float measurementVCC() 
{
  initADC0();
  ADCSRA |= _BV(ADSC);                 // Start conversion
  while ((ADCSRA & _BV(ADSC))) { ; }   // measure
  return static_cast<float>(INTERNxRESOLUTION / ADCW) / 1000;
}

void setup() {
  hc12.begin(4800);
  if (!sht31.begin(SHT31_ADDR)) {
    while (1);
  }
  // Set unused pins to INPUT_PULLUP to save power.
  for (auto pin : UNUSEDPINS) { pinMode(pin, INPUT_PULLUP); }

  // switch off ADC -320µA
  ADCSRA &= ~(1 << ADEN);
  delay(2000);

  // enable the watchdog
  enableWatchdog();
}

void loop() 
{
  float Temperatur = sht31.readTemperature();
  float Luftfeuchtigkeit = sht31.readHumidity();
  float vcc = measurementVCC();

  char toSend[17];  // Increased buffer size to accommodate VCC data
  if (!isnan(Temperatur) && !isnan(Luftfeuchtigkeit)) {
    char tempData[6];
    char humData[4];
    char vccData[5];
    char trenner[] = ",";

    // 4 is mininum width, 1 is precision; float value is copied onto buff
    dtostrf(Temperatur, 4, 1, tempData);
    dtostrf(Luftfeuchtigkeit, 2, 0, humData);
    dtostrf(vcc, 1, 2, vccData);  // Adjust precision as needed

    strcpy(toSend, tempData);
    strcat(toSend, trenner);
    strcat(toSend, humData);
    strcat(toSend, trenner);
    strcat(toSend, vccData);
    
  } else {
    strcpy(toSend, "99.9,99,");   // Error
  }
  hc12.print(toSend);   // Transmitting data with the HC12 transmitter
  // deep sleep
  for (uint8_t i = 0; i < WATCHDOG_WAKEUPS_TARGET; i++) { enterSleep(); }
}

Der Testaufbau: (wurde erst auf einem Steckboard aufgebaut)


Über jede unterstützung wäre ich sehr dankbar😊

Bin ich blind oder fehlt #include <TinyWireM.h>
Dazu kommt das die Adafruit sehr Dicke lib ist, reicht der Platz auf dem Tiny?
Schau mal hier

Wolle hat auch was :wink: ziemlich unten auf der Seite

Keine Ahnung :wink:

Alles gut, war ein falscher Fehler. :wink:

@migel_kryeziu So jetzt habe Dir was gefunden :wink: dafür zeige Bitte mir den Topic wo wir die Schriftarten gebaut haben.

wie meinst du das ?

Dort wo erklärt wurde das mit data Upload und mit processing wie man eigene Fonts baut.

Achso, das hier:

ich habe mir das Angeschaut und die Lib nach der Anleitung Modifiziert, jetzt mäckert der Compeiler:

D:\Apps\Arduino-1.8.19 Portable\portable\sketchbook\libraries\Grove_SHT31_Temp_Humi_Sensor-master\SHT31.cpp:15:7: error: prototype for 'float SHT31::getTemperature()' does not match any in class 'SHT31'
 float SHT31::getTemperature(void) {
       ^~~~~
In file included from D:\Apps\Arduino-1.8.19 Portable\portable\sketchbook\libraries\Grove_SHT31_Temp_Humi_Sensor-master\SHT31.cpp:1:0:
D:\Apps\Arduino-1.8.19 Portable\portable\sketchbook\libraries\Grove_SHT31_Temp_Humi_Sensor-master\SHT31.h:24:11: error: candidate is: float SHT31::getTemperature(bool)
     float getTemperature(bool S = false);
           ^~~~~~~~~~~~~~
D:\Apps\Arduino-1.8.19 Portable\portable\sketchbook\libraries\Grove_SHT31_Temp_Humi_Sensor-master\SHT31.cpp:26:32: error: no 'uint16_t SHT31::readStatus()' member function declared in class 'SHT31'
 uint16_t SHT31::readStatus(void) {

Ich bin überfragt

Der beilspielsketch von Wolle: (das Oled Display habe ich)

#include <TinyWireM.h>
#include <Tiny4kOLED.h>
#include <SHT31.h>

uint8_t width = 128;
uint8_t height = 64;

SHT31 sht31 = SHT31();

void setup() {
  TinyWireM.begin();
  oled.begin(width, height, sizeof(tiny4koled_init_128x64br), tiny4koled_init_128x64br);
  oled.setFont(FONT6X8);
  oled.clear();
  oled.on();
  
  oled.setCursor(0, 0);
  sht31.begin();
  sht31.heater(false); // heater off, with "true" it's on -> can remove condensated water, 
                       // but gives false temperature values (about 3 degrees too high);
}

void loop() {
  float temp = sht31.getTemperature();
  float hum = sht31.getHumidity();
  
  oled.setCursor(0,0);
  oled.print("Temp.   [*C]: ");
  oled.print(temp);
  oled.clearToEOL();
  
  oled.setCursor(0,2); //10
  oled.print("Humidity [%]: ");
  oled.print(hum);
  oled.clearToEOL();
  
  delay(2000);
}

Habe kein 85 :roll_eyes:

der nutzt kein Grove !

Der in der Lib hinterlegte Beilspielsketch das gleiche Problem

ich habs hinbekommen es Funktioniert, ich habe zusätzlich noch etwas in der SHT31.cpp Datei was geändert was bei Wolle nicht beschrieben war.

float SHT31::getTemperature(void) {
  if (! getTempHum()) return NAN;
  return temp;
}

Wurde ersetzt durch:

float SHT31::getTemperature(bool S) {
  if (! getTempHum()) return NAN;
  return temp;
}

Die Lib (nochmals von mir angepasst)
Grove_SHT31_Temp_Humi_Sensor-master
Grove_SHT31_Temp_Humi_Sensor-master.zip (5,2 KB)

Die Rückseite der Platine:

1 Like

Geht doch :wink:
Hinter den % ist ein Space zu viel :wink:

War eher zufall, aber hab die Zip hier bereit gestellt für andere wenn es probleme geben sollte :blush:bin froh das endlich Funzt.

Mit absicht, als platzhalter das wenn das 100% steht nicht aus dem Display herraus geht

Dan schreib doch Rechtsbündig :wink:
TR, BR was auch immer du nutzt
Ist doch die TFT_eSPI, oder?

genau

tft.h

/***************************************************************************************
**                         Section 5: Font datum enumeration
***************************************************************************************/
//These enumerate the text plotting alignment (reference datum point)
#define TL_DATUM 0 // Top left (default)
#define TC_DATUM 1 // Top centre
#define TR_DATUM 2 // Top right
#define ML_DATUM 3 // Middle left
#define CL_DATUM 3 // Centre left, same as above
#define MC_DATUM 4 // Middle centre
#define CC_DATUM 4 // Centre centre, same as above
#define MR_DATUM 5 // Middle right
#define CR_DATUM 5 // Centre right, same as above
#define BL_DATUM 6 // Bottom left
#define BC_DATUM 7 // Bottom centre
#define BR_DATUM 8 // Bottom right
#define L_BASELINE  9 // Left character baseline (Line the 'A' character would sit on)
#define C_BASELINE 10 // Centre character baseline
#define R_BASELINE 11 // Right character baseline

/*************************************************************

Macht
tft.setTextDatum(BR_DATUM);
Als Beispiel.

Ah, vielen dank, gut zu wissen😊

Ein kleines problem habe ich noch, wo ich nicht weiter komme, wenn ich den HC12 betreibe mit FU2 (Extremer Stromsparmodus) werden beim empfangen die erste zahl nie erkannt, stadessen wird ein "?" empfangen und somit nichts auf dem Display angezeigt.

Der sendecode:

#include <Arduino.h>
#include <avr/wdt.h>
#include <avr/sleep.h>

#include <TinyWireM.h>
#include <SHT31.h>
SHT31 sht31 = SHT31();

#include <SoftwareSerial.h>
SoftwareSerial hc12(4, 3);   // TX = 4, RX = 3

constexpr byte UNUSEDPINS[] {4};
constexpr byte WATCHDOG_WAKEUPS_TARGET {37};   // 8 * 7 = 56 seconds between each data collection

// watchdog ISR
ISR(WDT_vect) 
{
  // nothing to do here, just wake up
}

void enableWatchdog() 
{
  cli();
  MCUSR &= ~(1 << WDRF);
  WDTCR |= (1 << WDCE) | (1 << WDE);
  WDTCR = 1 << WDP0 | 1 << WDP3;
  WDTCR |= (1 << WDIE);
  sei();
}

// function to go to sleep
void enterSleep(void) {
  ADCSRA &= ~(1 << ADEN);              // switch off ADC -320µA
  set_sleep_mode(SLEEP_MODE_PWR_DOWN); // SLEEP_MODE_PWR_DOWN for lowest power consumption. 
  sleep_enable();
  sleep_mode();
  sleep_disable();
}

void initADC0() {
  // Read 1.1V reference as input with reference operating voltage vcc
  // Reference Vcc and analog input = internal reference 1.1V

 // Initialise ADC with REFS[2:0] is 0 = VCC as Ref,  MUX[3:0] 1100 = Vbg as Input,
  ADMUX = _BV(MUX3) | _BV(MUX2);
  bitSet(ADCSRA, ADEN);   // Enable
  delay(100);              // Wait until the reference has stabilized
  
  // After activating the ADC, a "dummy readout" is recommended.
  // In other words, a value is read and discarded to allow the ADC to "warm up"
  ADCSRA |= _BV(ADSC);                 // Start conversion
  while ((ADCSRA & _BV(ADSC))) { ; }   // measure
  (void)ADCW;                          // Discard dummy readout..
}

constexpr uint16_t INTERN {1070};   // determined per IC
constexpr uint32_t INTERNxRESOLUTION {INTERN * 1024UL};

float measurementVCC() 
{
  initADC0();
  ADCSRA |= _BV(ADSC);                 // Start conversion
  while ((ADCSRA & _BV(ADSC))) { ; }   // measure
  return static_cast<float>(INTERNxRESOLUTION / ADCW) / 1000;
}

void setup() {
  TinyWireM.begin();
  hc12.begin(4800);
  if (!sht31.begin(SHT31_ADDR)) {
    while (1);
  }
  // Set unused pins to INPUT_PULLUP to save power.
  for (auto pin : UNUSEDPINS) { pinMode(pin, INPUT_PULLUP); }

  // switch off ADC -320µA
  ADCSRA &= ~(1 << ADEN);
  delay(2000);

  // enable the watchdog
  enableWatchdog();
}

void loop() 
{
  float temp = sht31.getTemperature();
  float hum = sht31.getHumidity();
  float vcc = measurementVCC();

  char toSend[17];  // Increased buffer size to accommodate VCC data
  if (!isnan(temp) && !isnan(hum)) {
    char tempData[6];
    char humData[4];
    char vccData[5];
    char trenner[] = ",";

    // 4 is mininum width, 1 is precision; float value is copied onto buff
    dtostrf(temp, 4, 1, tempData);
    dtostrf(hum, 2, 0, humData);
    dtostrf(vcc, 1, 2, vccData);  // Adjust precision as needed

    strcpy(toSend, tempData);
    strcat(toSend, trenner);
    strcat(toSend, humData);
    strcat(toSend, trenner);
    strcat(toSend, vccData);
    
  } else {
    strcpy(toSend, "99.9,99,");   // Error
  }
  hc12.print(toSend);   // Transmitting data with the HC12 transmitter
  // deep sleep
  for (uint8_t i = 0; i < WATCHDOG_WAKEUPS_TARGET; i++) { enterSleep(); }
}

Test Sketch zum empfangen:

#include <SoftwareSerial.h>

// Definieren Sie die serielle Verbindung zum HC-12-Modul
SoftwareSerial HC12Serial(26, 27); // RX, TX

void setup() {
  // Beginnen Sie die Kommunikation mit dem seriellen Monitor
  Serial.begin(9600);

  // Beginnen Sie die Kommunikation mit dem HC-12-Modul
  HC12Serial.begin(4800);
  delay(500);  // Warten Sie kurz, um sicherzustellen, dass alle Daten empfangen wurden
}

void loop() {
  // Lesen Sie Daten vom HC-12-Modul und senden Sie sie an den seriellen Monitor
  if (HC12Serial.available()) {
    delay(100);  // Warten Sie kurz, um sicherzustellen, dass alle Daten empfangen wurden
    while (HC12Serial.available()) {
      char c = HC12Serial.read();
      Serial.print(c);
    }
  }

  // Lesen Sie Daten vom seriellen Monitor und senden Sie sie an das HC-12-Modul
  while (Serial.available()) {
    char c = Serial.read();
    HC12Serial.print(c);
  }
}

So siehts es im Ser Mon aus:

⸮5.2,49,4.89

Statt dem "?" sollte da eine 2 stehen
Das hat wohl was mit der verzögerung zu tun wenn der HC12 aus dem standby erwacht, wird der HC12 betrieben ohne den FU2 Modus habe ich das Problem am empfänger nicht, mit
delay(500); an verschiedenen stellen habe ich es schon probiert, erfolglos