Светодиод мигает в цикле в состоянии

Поэтому я объясню, что я хочу получить. Я считываю температуру с DS18B20 и показываю ее на ЖК-дисплее. У меня есть один светодиод на контакте 3, который мигает при чтении температуры и обновлении экрана. У меня есть еще один светодиод на контакте 4, который должен гореть, когда температура больше 25 и меньше 30, и я хочу, чтобы он мигал, когда температура больше 30. То, что я получаю, это мигание, но не как одно мигание каждые 10 мс, но это ждет, пока весь цикл снова начнет мигать. Могу ли я сделать отдельно, чтобы этот светодиод мигал независимо, когда условие истинно? С установленным интервалом, например, 10 мс, который не будет ждать весь цикл.

вот мой пример кода:

    #include <OneWire.h>

#include <Wire.h> 
#include <LiquidCrystal_I2C.h>



LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Устанавливаем I2C-адрес ЖК-дисплея

//LiquidCrystal_I2C lcd (0x27, ПОЛОЖИТЕЛЬНО); // Устанавливаем I2C-адрес ЖК-дисплея
OneWire  ds(2);

unsigned long previousMillis = 0;
const long interval = 1000;
int ledState = LOW;
void setup()
{
pinMode(3, OUTPUT);
pinMode(4, OUTPUT);

  lcd.begin(16,2);               // инициализируем ЖК-дисплей

}

void loop()

{
  unsigned long currentMillis = millis();

  byte i;
  byte present = 0;
  byte type_s;
  byte data[12];
  byte addr[8];
  float celsius;

  if ( !ds.search(addr)) {
    ds.reset_search();
    delay(250);
    return;
  }

  Serial.println();

  // первый байт ПЗУ указывает, какая микросхема
  switch (addr[0]) {
    case 0x10:
      Serial.println("  Chip = DS18S20");  // или старый DS1820
      type_s = 1;
      break;
    case 0x28:
      Serial.println("  Chip = DS18B20");
      type_s = 0;
      break;
    case 0x22:
      Serial.println("  Chip = DS1822");
      type_s = 0;
      break;
    default:
      Serial.println("Device is not a DS18x20 family device.");
      return;
  } 

  ds.reset();
  ds.select(addr);
  ds.write(0x44, 1);        // начинаем преобразование, в конце с включенным питанием паразита

  delay(850);     // может 750 мс хватит, может нет
  // здесь мы могли бы выполнить ds.depower(), но об этом позаботится сброс.

  present = ds.reset();
  ds.select(addr);    
  ds.write(0xBE);         // Чтение блокнота

  Serial.print("  Data = ");
  Serial.print(present, HEX);
  Serial.print(" ");
  for ( i = 0; i < 9; i++) {           // нам нужно 9 байт
    data[i] = ds.read();
    Serial.print(data[i], HEX);
    Serial.print(" ");
  }
  Serial.print(" CRC=");
  Serial.print(OneWire::crc8(data, 8), HEX);
  Serial.println();

  // Преобразование данных в фактическую температуру
  // поскольку результатом является 16-битное целое число со знаком, оно должно
  // храниться в типе "int16_t", который всегда равен 16 битам
  // даже при компиляции на 32-битном процессоре.
  int16_t raw = (data[1] << 8) | data[0];
  if (type_s) {
    raw = raw << 3; // 9-битное разрешение по умолчанию
    if (data[7] == 0x10) {
      // "количество оставшихся" дает полное 12-битное разрешение
      raw = (raw & 0xFFF0) + 12 - data[6];
    }
  } else {
    byte cfg = (data[4] & 0x60);
    // при более низком разрешении младшие биты не определены, поэтому обнулим их
    if (cfg == 0x00) raw = raw & ~7;  // 9-битное разрешение, 93,75 мс
    else if (cfg == 0x20) raw = raw & ~3; // 10-битное разрешение, 187,5 мс
    else if (cfg == 0x40) raw = raw & ~1; // 11-битное разрешение, 375 мс
    //// по умолчанию разрешение 12 бит, время преобразования 750 мс
  }
  celsius = (float)raw / 16.0;


  digitalWrite(3, HIGH);   // включаем светодиод (HIGH - уровень напряжения)
  delay(10);              // ждем секунду
  digitalWrite(3, LOW);    // выключаем светодиод, понижая напряжение


   lcd.home ();
   lcd.print("Reading 1");
   lcd.setCursor( 0, 1);
   lcd.print("temp:");
   lcd.print(celsius);
   lcd.print("*C");

   if (celsius >= 25 && celsius < 30) {
    digitalWrite(4,HIGH);
   } else if (celsius >= 30) {
blink1();
   } else {
    digitalWrite(4,LOW);
   }

}

void blink1() {
digitalWrite(4,HIGH);
delay(50);
digitalWrite(4,LOW);
}

, 👍-1


1 ответ


2

Попробуйте вот это:

#include <OneWire.h>

#include <Wire.h> 
#include <LiquidCrystal_I2C.h>



LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Устанавливаем I2C-адрес ЖК-дисплея

//LiquidCrystal_I2C lcd (0x27, ПОЛОЖИТЕЛЬНО); // Устанавливаем I2C-адрес ЖК-дисплея
OneWire  ds(2);

const long interval = 1000; //Интервал, с которым мигает (миллисекунды)
unsigned long previousMillis = 0;
int ledState = LOW;
void setup()
{
pinMode(3, OUTPUT);
pinMode(4, OUTPUT);

  lcd.begin(16,2);               // инициализируем ЖК-дисплей

}

void loop()
{

  byte i;
  byte present = 0;
  byte type_s;
  byte data[12];
  byte addr[8];
  float celsius;

  if ( !ds.search(addr)) {
    ds.reset_search();
    delay(250);
    return;
  }

  Serial.println();

  // первый байт ПЗУ указывает, какая микросхема
  switch (addr[0]) {
    case 0x10:
      Serial.println("  Chip = DS18S20");  // или старый DS1820
      type_s = 1;
      break;
    case 0x28:
      Serial.println("  Chip = DS18B20");
      type_s = 0;
      break;
    case 0x22:
      Serial.println("  Chip = DS1822");
      type_s = 0;
      break;
    default:
      Serial.println("Device is not a DS18x20 family device.");
      return;
  } 

  ds.reset();
  ds.select(addr);
  ds.write(0x44, 1);        // начинаем преобразование, в конце с включенным питанием паразита

  delay(850);     // может 750 мс хватит, может нет
  // здесь мы могли бы выполнить ds.depower(), но об этом позаботится сброс.

  present = ds.reset();
  ds.select(addr);    
  ds.write(0xBE);         // Чтение блокнота

  Serial.print("  Data = ");
  Serial.print(present, HEX);
  Serial.print(" ");
  for ( i = 0; i < 9; i++) {           // нам нужно 9 байт
    data[i] = ds.read();
    Serial.print(data[i], HEX);
    Serial.print(" ");
  }
  Serial.print(" CRC=");
  Serial.print(OneWire::crc8(data, 8), HEX);
  Serial.println();

  // Преобразование данных в фактическую температуру
  // поскольку результатом является 16-битное целое число со знаком, оно должно
  // храниться в типе "int16_t", который всегда равен 16 битам
  // даже при компиляции на 32-битном процессоре.
  int16_t raw = (data[1] << 8) | data[0];
  if (type_s) {
    raw = raw << 3; // 9-битное разрешение по умолчанию
    if (data[7] == 0x10) {
      // "количество оставшихся" дает полное 12-битное разрешение
      raw = (raw & 0xFFF0) + 12 - data[6];
    }
  } else {
    byte cfg = (data[4] & 0x60);
    // при более низком разрешении младшие биты не определены, поэтому обнулим их
    if (cfg == 0x00) raw = raw & ~7;  // 9-битное разрешение, 93,75 мс
    else if (cfg == 0x20) raw = raw & ~3; // 10-битное разрешение, 187,5 мс
    else if (cfg == 0x40) raw = raw & ~1; // 11-битное разрешение, 375 мс
    //// по умолчанию разрешение 12 бит, время преобразования 750 мс
  }
  celsius = (float)raw / 16.0;

   lcd.home ();
   lcd.print("Reading 1");
   lcd.setCursor( 0, 1);
   lcd.print("temp:");
   lcd.print(celsius);
   lcd.print("*C");

   if (celsius >= 25 && celsius < 30) {
    digitalWrite(4,HIGH);
   } else if (celsius >= 30) {
blink1();
   } else {
    digitalWrite(4,LOW);
   }

   unsigned long currentMillis = millis();

   if (currentMillis - previousMillis >= interval) {

     previousMillis = currentMillis;

     if (ledState == LOW) {
       ledState = HIGH;
     } else {
       ledState = LOW;
     }

     digitalWrite(3, ledState);
   }
}

void blink1() {
digitalWrite(4,HIGH);
delay(50);
digitalWrite(4,LOW);
}

а также обратите внимание, что я выбрал 1000 миллисекунд для интервала (равного 1 секунде), поэтому, если вы хотите 10 мс, как в своем первом сообщении, измените const long interval на 10

,