Попытка использовать DHT11 с дисплеем PxMatrix на плате ESP32 - PullRequest
0 голосов
/ 03 апреля 2020

Я пытаюсь отобразить показания DHT11 на светодиодной матрице. Я могу заставить работать дисплей basi c, проблема в том, когда я также показываю время на дисплее. Я начал с Morphing Clock в качестве основы для времени, затем использовал код датчика Adafruit для считывания DHT11. Кажется, проблема связана с "

timerAlarmWrite(timer, 2000, true);

", который настроен для вызова:

void IRAM_ATTR display_updater(){
  // Increment the counter and set the time of ISR
  portENTER_CRITICAL_ISR(&timerMux);
  display.display(10);
  portEXIT_CRITICAL_ISR(&timerMux);
}

Если я замедляю таймер, я могу получить показания с DHT11, но отображение времени трансформации не не достаточно обновляюсь, чтобы выглядеть плавно. Я новичок в кодировании для этих устройств, поэтому я не уверен, где я должен искать, чтобы эти вещи переставляли друг друга. Вот полное приложение, если таймер установлен на что-то выше 25000 вы будете получать временные результаты в большинстве случаев, но чем меньше яркость и тем больше двоеточие sh (они не должны).

#define double_buffer
#include <PxMatrix.h>
#include <WiFi.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
#include "Digit.h"

#include <Adafruit_Sensor.h>
#include <DHT.h>

const char* ssid     = "Gallifrey";
const char* password = "ThisIsAGoodPlaceToPutAPassword!";

// ESP32 Pins for LED MATRIX
#define P_LAT 22
#define P_A 19
#define P_B 23
#define P_C 18
#define P_D 5
#define P_E 15  // NOT USED for 1/16 scan
#define P_OE 2
hw_timer_t * timer = NULL;
portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;

PxMATRIX display(64,32,P_LAT, P_OE,P_A,P_B,P_C,P_D,P_E);

void IRAM_ATTR display_updater(){
  // Increment the counter and set the time of ISR
  portENTER_CRITICAL_ISR(&timerMux);
  display.display(10);
  portEXIT_CRITICAL_ISR(&timerMux);
}

// Define NTP Client to get time
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP);

// Variables to save date and time
String formattedDate;
String dayStamp;
String timeStamp;

unsigned long prevEpoch;
byte prevhh;
byte prevmm;
byte prevss;


//====== Digits =======
Digit digit0(&display, 0, 63 - 1 - 9*1, 17, display.color565(0, 250, 0));
Digit digit1(&display, 0, 63 - 1 - 9*2, 17, display.color565(0, 250, 0));
Digit digit2(&display, 0, 63 - 4 - 9*3, 17, display.color565(0, 250, 0));
Digit digit3(&display, 0, 63 - 4 - 9*4, 17, display.color565(0, 250, 0));
Digit digit4(&display, 0, 63 - 7 - 9*5, 17, display.color565(0, 250, 0));
Digit digit5(&display, 0, 63 - 7 - 9*6, 17, display.color565(0, 250, 0));


#define DHTPIN 27
#define DHTTYPE DHT11

//DHT_Unified dht(DHTPIN, DHTTYPE);
DHT dht(DHTPIN, DHTTYPE);
//DHT dht;

const uint32_t delayMS = 6000;
uint32_t lastRead;

void setup() {

  display.begin(16); // 1/16 scan
  display.setFastUpdate(true);

   // Initialize Serial Monitor
  Serial.begin(115200);

  pinMode(DHTPIN, INPUT_PULLUP);
  dht.begin();
//  // Set delay between sensor readings based on sensor details.
  lastRead = 0;

  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  timer = timerBegin(0, 80, true);
  timerAttachInterrupt(timer, &display_updater, true);
  timerAlarmWrite(timer, 1500, true); /// The Problem is Here!!!???!!!!?
  timerAlarmEnable(timer);

  display.fillScreen(display.color565(0, 0, 0));
  digit1.DrawColon(display.color565(100, 175, 0));
  digit3.DrawColon(display.color565(100, 175, 0));

  // Print local IP address and start web server
  Serial.println("");
  Serial.println("WiFi connected.");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

  // Initialize a NTPClient to get time
  timeClient.begin();
  timeClient.setTimeOffset(-28800);

}

void loop() {

  while(!timeClient.update()) {
    timeClient.forceUpdate();
  }

  formattedDate = timeClient.getFormattedDate();

  // Extract date
  int splitT = formattedDate.indexOf("T");
  dayStamp = formattedDate.substring(0, splitT);

  // Extract time
  timeStamp = formattedDate.substring(splitT+1, formattedDate.length()-1);

  displayLocalTemp();
  updateTimeDisplay();

}

String readDHTTemperature() {
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  // Read temperature as Celsius (the default)
  float t = dht.readTemperature(true);
  // Read temperature as Fahrenheit (isFahrenheit = true)
  //float t = dht.readTemperature(true);
  // Check if any reads failed and exit early (to try again).
  if (isnan(t)) {    
    Serial.println("Failed to read from DHT sensor!");
    return "--";
  }
  else {
    Serial.println(t);
    return String(t);
  }
}

String readDHTHumidity() {
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  float h = dht.readHumidity();
  if (isnan(h)) {
    Serial.println("Failed to read from DHT sensor!");
    return "--";
  }
  else {
    Serial.println(h);
    return String(h);
  }
}

void displayLocalTemp() {

  uint32_t currentTime = millis();
  uint32_t waited = currentTime - lastRead;

  static String lastTemp;
  static String lastHumid;

  if (waited > delayMS) {
    lastRead = currentTime;

    String temp = readDHTTemperature();
    String humidity = readDHTHumidity();
    String preTemp = "T:";
    String preHumidity = "H:";
    String tempDisplay = preTemp + temp;
    String humidDisplay = preHumidity + humidity;

    Serial.print("temp: ");
    Serial.print(temp);
    Serial.print(" -- humidity: ");
    Serial.println(humidity);

    display.setTextColor(display.color565(0,0,0));
    display.setCursor(20,16);
    display.print(lastTemp);
    display.setCursor(20,25);
    display.print(lastHumid);

    display.setTextColor(display.color565(0,255,0));
    display.setCursor(20,16);
    display.print(tempDisplay);
    display.setCursor(20,25);
    display.print(humidDisplay);

    lastTemp = tempDisplay;
    lastHumid = humidDisplay;
  }

}

void updateTimeDisplay() {

  unsigned long epoch = timeClient.getEpochTime();

  if (epoch != prevEpoch) {
    int hh = timeClient.getHours();
    int mm = timeClient.getMinutes();
    int ss = timeClient.getSeconds();

    if (hh > 12) hh = hh % 12;

    if (prevEpoch == 0) { // If we didn't have a previous time. Just draw it without morphing.
      digit0.Draw(ss % 10);
      digit1.Draw(ss / 10);
      digit2.Draw(mm % 10);
      digit3.Draw(mm / 10);
      digit4.Draw(hh % 10);
      digit5.Draw(hh / 10);
    }
    else
    {
      // epoch changes every miliseconds, we only want to draw when digits actually change.
      if (ss!=prevss) { 
        int s0 = ss % 10;
        int s1 = ss / 10;
        if (s0!=digit0.Value()) digit0.Morph(s0);
        if (s1!=digit1.Value()) digit1.Morph(s1);
        //ntpClient.PrintTime();
        prevss = ss;
      }

      if (mm!=prevmm) {
        int m0 = mm % 10;
        int m1 = mm / 10;
        if (m0!=digit2.Value()) digit2.Morph(m0);
        if (m1!=digit3.Value()) digit3.Morph(m1);
        prevmm = mm;
      }

      if (hh!=prevhh) {
        int h0 = hh % 10;
        int h1 = hh / 10;
        if (h0!=digit4.Value()) digit4.Morph(h0);
        if (h1!=digit5.Value()) digit5.Morph(h1);
        prevhh = hh;
      }
    }
    prevEpoch = epoch;
  }

}

1 Ответ

0 голосов
/ 03 апреля 2020

Вы можете попытаться назначить задачи явно ядру.
Когда вы начнете играть с выполнением многоядерного кода ESP32, помните о следующих проблемах:

  • И настройка, и основной oop функции выполняются с приоритетом 1.
  • Arduino main l oop работает на ядре 1.
  • Выполнение закреплено, поэтому не ожидается, что ядро ​​изменится во время выполнения программы
  • В FreeRTOS (базовая ОС) задачам назначен приоритет, который планировщик использует для определения того, какая задача будет запускаться.
  • Готовые к запуску задачи с высоким приоритетом будут иметь приоритет над более низкими приоритетные задачи, что означает, что до тех пор, пока может выполняться задача с более высоким приоритетом, задача с более низким приоритетом не будет иметь ЦП.
  • ВНИМАНИЕ общие ресурсы, такие как Serial, могут быть потенциальными проблемами. Из-за двух основных задач, связанных с несогласованным доступом к одному и тому же оборудованию, могут возникнуть взаимные блокировки и сбои

В целях реализации необходимо учитывать, что приоритеты FreeRTOS назначаются от 0 до N, где меньшие числа соответствуют более низкие приоритеты. Итак, самый низкий приоритет - 0.
Прежде всего, объявите глобальную переменную, которая будет содержать номер ядра, на котором будет закреплено запускаемое задание FreeRTOS

static int taskCore = 0; // The core the task should run on

Теперь создайте присвоение основная задача в Setup ()

xTaskCreatePinnedToCore(
                myCoreTask,   /* Function to implement the task */
                "myCoreTask", /* Name of the task */
                10000,      /* Stack size in words */
                NULL,       /* Task input parameter */
                0,          /* Priority of the task */
                NULL,       /* Task handle. */
                taskCore);  /* Core where the task should run */

Вот тестовая функция, которую вы вызываете в l oop ()

void myCoreTask( void * pvParameters ){
   while(true){
      Serial.println("Task running on core ");
      Serial.print(xPortGetCoreID());
    // This is here to show that other tasks run 
     // NEVER use in production
      delay(1000); 
    }
}

Надеюсь, это даст вам представление о том, как решить вашу проблему, читайте подробнее здесь RTOS и здесь ESP32-IDF

...