Условная конструкция

marat-ufa83
Offline
Зарегистрирован: 21.04.2019
/*------------------------
      Leds used here are WS2812B, 3 leds by segment
   total = (3*7)* 4numbers  + 2 dots = 86 leds
   Led controlled with FastLeds Lib on Pin 6
   Brightness sensor on A3
   Temperature sensor on A2
   RTC Modul on A4 A5
   I'm using 5V 3A Power supply
   Используются 2 цвета: красный-часы, зеленый-дата, желтый-температура + динамическая яркость светодиодов
   Buzzer D2
*/
#include <DS3232RTC.h>
#include <Time.h>
#include <Wire.h>
#include <FastLED.h>
#include <OneWire.h>
#include <DS18B20.h>
#include "GyverTimer.h"

#define NUM_LEDS 86  //3*7*4 +2  Number of LED controles (remember I have 3 leds / controler
#define LED_TYPE    WS2812B
#define BRIGHTNESS_DEFAULT  230 //яркость дисплея по умолчанию
#define IMPULSE_TONE 500     // продолжительность звучания\паузы гудка
#define LED_PIN 6          //пин подключения светодиодной ленты
#define ONE_WIRE_BUS A2   //пин подключения датчика температуры
#define BUZZER 2         //пин подключения реле звукового оповещения
#define PHOTOCELL A3      //пин подключения фоторезистора
char incoming_command = 'H';
int brightness = 0;
int  auto_brightness = 1;

//brightness
int photocellReading; // the analog reading from the analog resis
int led_on = 1;

//LEDS COLORS
volatile boolean animate = true;
volatile long animation_change_timeout;
unsigned long previousMillis1 = 0;        // будет хранить последний раз, когда реле был обновлен
const long intervalVision = 5000;           // интервал отображения Temp and date
unsigned long previousMillis2 = 0;        // будет хранить последний раз, когда  был обновлен счетчик гудка
const long intervalSong = 3000;           //интервал звучания гудка

//ТЕМПЕРАТУРА
OneWire oneWire(ONE_WIRE_BUS);
DS18B20 sensor(&oneWire);
int temperatureOutdoor; // Глобальная переменная для хранения значение температуры с датчика DS18B20
long lastUpdateTime = 0; // Переменная для хранения времени последнего считывания с датчика
const int TEMP_UPDATE_TIME = 1000; // Определяем периодичность проверок

//ТАЙМЕРЫ
GTimer_ms tempTimer(30000);            // таймер вывода температуры (
GTimer_ms dateTimer(60000);           // таймер вывода даты

//ГУДОК
int signalRabDay [8] = {830, 1014, 1015, 1230, 1315, 1500, 1515, 1715};    // массив цифр определяющих время сработки
//звукового оповещения в рабочие дни
int signalHolyDay [8] = {800, 1000, 1015, 1200, 1230, 1500, 1515, 1600};    //время сработки в выходные дни
bool relayState = false;   //состояние реле подачи звука
bool Flag_1;            //флаг совпадения элемента массива с тек временем
bool Flag_2;            //флаг выполнения условия секунды от  0-3
int sec;                    //глобальная переменная хранения секунд

CRGB leds[NUM_LEDS]; // Define LEDs strip
// 10 digit :0...10, each digit is composed of 7 segments of 3 leds

byte digits[10][21] = {  //2-мерный массив цифр on 7 segment
  //  1  2  3  4  5  6  7  8  9  10 11 12 13 14 15 16 17 18 19 20 21
  {    0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1  }, // Digit 0

  {    0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1  }, // Digit 1

  {    1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0  }, // Digit 2

  {    1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1  }, // Digit 3

  {    1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1  }, // Digit 4

  {    1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1  }, // Digit 5

  {    1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1  }, // Digit 6

  {    0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1  }, // Digit 7

  {    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1  }, // Digit 8

  {    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1  }  // Digit 9
};

bool Dot = true; //Dot state
int last_digit = 0;
long dotsLedColor = CRGB::Red;;     // Цвет отображени точек (in hex)
long timeLedColor = CRGB::Red;     // Цвет отображения времени (in hex)
long dateLedColor = CRGB::Green;   // Цвет отображения даты (in hex)
long tempLedColor = CRGB::Yellow;  // Цвет отображения температуры (in hex)

void setup() {
  Serial.begin(9600);
  Wire.begin();
  FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS);
  FastLED.setBrightness(  BRIGHTNESS_DEFAULT );
  sensor.begin();
  pinMode (BUZZER, OUTPUT);
}

// Проверьте датчик освещенности и установите яркость соответственно
void BrightnessCheck() {
  const byte brightnessLow = 20; // Low brightness value
  const byte brightnessHigh = 70; // High brightness value
  int sensorValue = analogRead(PHOTOCELL); // Read sensor
  sensorValue = map(sensorValue, 0, 1023, 230, 10);
  constrain (sensorValue, 230, 10);
  //  Serial.print("Sensor is: ");Serial.println(sensorValue);
  LEDS.setBrightness(sensorValue);
};

// Получение времени в одну цифру
int GetTime() {
  tmElements_t Now;
  RTC.read(Now);
  //time_t Now = RTC.Now();// Получение текущего времени и его сохранение в объекте DateTime
  int hour = Now.Hour;
  int minutes = Now.Minute;
  int second = Now.Second;
  sec = second;
  
  //используйте это, чтобы мигать ваши точки каждую секунду
  if (second % 2 == 0) {
    Dot = false;
  }
  else {
    Dot = true;
  };

  //легко манипулировать 2250, а не часами = 10 минут = 50
  return (hour * 100 + minutes);
}

//функция вывода дня и месяца
int DayMonth() {
  tmElements_t Now;
  RTC.read(Now);
  int day = Now.Day;
  int month = Now.Month;
  //  int weekday = Now.
  return (day * 100 + month);
}

// Конвертировать время в массив, необходимый для отображения
void TimeToArray() {
  int Now = GetTime(); // Получить время
  //  Serial.print ("Time now = ");
  //  Serial.println (Now);
  int cursor = 86;
  if (Dot) {
    leds[42] = dotsLedColor;
    leds[43] = dotsLedColor;
  }
  else {
    leds[42] = 0x000000;
    leds[43] = 0x000000;
  };

  for (int i = 1; i <= 4; i++) {
    int digit = Now % 10; // Получить последнюю цифру времени
    if (i == 1) {
      cursor = 65;
      for (int k = 0; k <= 20; k++) {

        if (digits[digit][k] == 1) {
          leds[cursor] = timeLedColor;
        }
        else if (digits[digit][k] == 0) {
          leds[cursor] = 0x000000;
        };

        cursor ++;
      }; // fin for

      if (digit != last_digit)
      {
        //        DateToArray();
        //        Temp();
        //        fadefonction();
        //        ledColor =  ColorTable[random(2)];
      }
      last_digit = digit;
    }// fin if

    else if (i == 2) {

      cursor = 44;
      for (int k = 0; k <= 20; k++) {

        if (digits[digit][k] == 1) {
          leds[cursor] = timeLedColor;
        }
        else if (digits[digit][k] == 0) {
          leds[cursor] = 0x000000;
        };
        cursor ++;
      };
      // Serial.println();
    }
    else if (i == 3) {
      cursor = 21;

      for (int k = 0; k <= 20; k++) {

        if (digits[digit][k] == 1) {
          leds[cursor] = timeLedColor;
        }

        else if (digits[digit][k] == 0) {
          leds[cursor] = 0x000000;
        };
        cursor ++;
      };

    }
    else if (i == 4) {
      cursor = 0;
      for (int k = 0; k <= 20; k++) {
        if (digits[digit][k] == 1) {
          leds[cursor] = timeLedColor;
        }
        else if (digits[digit][k] == 0) {
          leds[cursor] = 0x000000;
        };
        cursor ++;
      };
    };
    Now /= 10;
  };
};

// Конвертировать дату в массив, необходимый для отображения
void DateToArray() {
  FastLED.clear();
  unsigned long currentMillis = millis();
  while (millis() - currentMillis < intervalVision) {
    FastLED.show();
    int Now = DayMonth(); // Get time
    int cursor = 86; //116

    for (int i = 1; i <= 4; i++) {
      int digit = Now % 10; // получение последней цифры из времени

      if (i == 1) {
        cursor = 65; //82
        for (int k = 0; k <= 20; k++) {
          if (digits[digit][k] == 1) {
            leds[cursor] = dateLedColor;
          }
          else if (digits[digit][k] == 0) {
            leds[cursor] = 0x000000;
          };
          cursor ++;
        }; // fin for
      }// fin if

      else if (i == 2) {

        cursor = 44;

        for (int k = 0; k <= 20; k++) {

          if (digits[digit][k] == 1) {
            leds[cursor] = dateLedColor;
          }

          else if (digits[digit][k] == 0) {
            leds[cursor] = 0x000000;
          };
          cursor ++;
        };
      }
      else if (i == 3) {
        cursor = 21;
        for (int k = 0; k <= 20; k++) {
          if (digits[digit][k] == 1) {
            leds[cursor] = dateLedColor;
          }
          else if (digits[digit][k] == 0) {
            leds[cursor] = 0x000000;
          };
          cursor ++;
        };
      }
      else if (i == 4) {
        cursor = 0;
        for (int k = 0; k <= 20; k++) {
          if (digits[digit][k] == 1) {
            leds[cursor] = dateLedColor;
          }
          else if (digits[digit][k] == 0) {
            leds[cursor] = 0x000000;
          };
          cursor ++;
        };
      };
      Now /= 10;

    };
  }
};

//пока не используется
void TimeAdjust() {
  int buttonH = digitalRead(5);
  int buttonM = digitalRead(4);
  if (buttonH == LOW || buttonM == LOW) {

    delay(500);

    tmElements_t Now;

    RTC.read(Now);
    int hour = Now.Hour;
    int minutes = Now.Minute;
    if (buttonH == LOW) {
      if (Now.Hour == 24) {
        Now.Hour = 1;
      }
      else {
        Now.Hour += 1;
      };

    }
    else {
      if (Now.Minute == 59) {
        Now.Minute = 0;
      }

      else {
        Now.Minute += 1;
      };

    };
    RTC.write(Now);

  }
}

/******IR check****
   Проверьте команду на последовательном порту, отправленную
    другой Arduino в зависимости от нажатой кнопки
*/
void IR_Check() {
  if (Serial.available() > 0) {
    // read the incoming byte:
    incoming_command = Serial.read();
    unsigned long startTime = 0;
    switch (incoming_command) {

      //colors
      case 'R' :
        //Serial.println("RED");
        timeLedColor = CRGB::Red;
        break;
      case 'B' :
        timeLedColor = CRGB::Blue;
        break;
      case 'G' :
        timeLedColor = CRGB::Green;
        break;
      case 'W' :
        timeLedColor = CRGB::White;
        break;
      case 'I' :
        timeLedColor = CRGB::OrangeRed;
        break;
      case 'J' :
        timeLedColor = CRGB::GreenYellow;
        break;
      case 'K' :
        timeLedColor = CRGB::MediumSlateBlue;
        break;
      case 'L' :
        timeLedColor = CRGB::Pink;
        break;
      case 'M' :
        timeLedColor = CRGB::DarkOrange;
        break;
      case 'N' :
        timeLedColor = CRGB::Aqua;
        break;
      case 'P' :
        timeLedColor = CRGB::DarkSlateBlue;
        break;
      case 'Q' :
        timeLedColor = CRGB::LightPink;
        break;
      case 'S' :
        timeLedColor = CRGB::LightSalmon;
        break;
      case 'U' :
        timeLedColor = CRGB::LightSeaGreen;
        break;
      case 'V' :
        timeLedColor = CRGB::Purple;
        break;
      case 'X' :
        timeLedColor = CRGB::Yellow;
        break;
      case 'Y' :
        timeLedColor = CRGB::Teal;
        break;
      case 'Z' :
        timeLedColor = CRGB::PaleVioletRed;
        break;
      case '*' :
        timeLedColor = CRGB::PaleTurquoise;
        break;

      case 'F' :
        //pick a random color but not working yet
        timeLedColor = CRGB( random8(), 100, 50);
        break;

      case '+' : //brighter
        brightness += 10;
        if (brightness > 255) brightness = 255;
        FastLED.setBrightness( brightness );
        auto_brightness = 0;
        break;
      case '-' :

        brightness -= 10;
        if (brightness < 10) brightness = 10;
        FastLED.setBrightness( brightness );
        auto_brightness = 0;
        break;

      case 'O' : //auto brightness

        if (led_on)
        {
          brightness = 0;
          led_on = 0;
        }
        else
        {
          brightness = BRIGHTNESS_DEFAULT ;
          led_on = 1;
        }

        FastLED.setBrightness( brightness );
        break;

      case 'T' : //Temp
        TempOutdoor();
        break;

      case 'a' : //Date
        DateToArray();
        break;

      case 'A' :
        auto_brightness = 1;
        break;

      default:
        break;
        //Serial.println("error");
    }//switch

    // say what you got:
    //Serial.print("I received: ");
    //Serial.println(incoming_command);

  }
};

//вывод внутренней температуры
/* void TempIndoor() {
  FastLED.clear();
  int cursor = 21; //65
  float t = RTC.temperature();
  int celsius = t / 4.0;
  Serial.print(celsius);
  unsigned long currentMillis = millis();
  while (millis() - currentMillis < interval) {
    FastLED.show();
    int cursor = 21; //65
    float t = RTC.temperature();
    int celsius = t / 4.0;
    for (int i = 1; i <= 2; i++) {

      int digit = celsius % 10; // get last digit in time
      Serial.print("digit");
      Serial.println(digit);
      if (i == 1) {

        for (int k = 0; k <= 20; k++) {

          if (digits[digit][k] == 1) {
            leds[cursor] = tempLedColor;
          }

          else if (digits[digit][k] == 0) {
            leds[cursor] = 0x000000;
          };

          cursor ++;

        }; // fin for

        FastLED.show();

      }// fin if

      else if (i == 2) {

        cursor = 0;

        for (int k = 0; k <= 20; k++) {

           if (digits[digit][k] == 1) {
            leds[cursor] = tempLedColor;
          }

          else if (digits[digit][k] == 0) {
            leds[cursor] = 0x000000;
          };

          cursor ++;

        };
      }

      celsius /= 10;
      FastLED.show();
    }
    for (int m = 44; m < 56; m++) {
      leds[m] = tempLedColor;
    }
    for (int m = 72; m < 83; m++) {
      leds[m] = tempLedColor;
    }
    FastLED.show();
    //check_for_input();
  }//fin while animate

  };
*/

//Температура на улице
void TempOutdoor() {
  FastLED.clear();
  int cursor = 21; //65
  if (millis() - lastUpdateTime > TEMP_UPDATE_TIME) {
    sensor.requestTemperatures();
    temperatureOutdoor = sensor.getTempC();
    Serial.print("Temp: ");
    Serial.println(temperatureOutdoor); // Выводим полученное значение температуры
    // Т.к. переменная temperature имеет тип int, дробная часть будет просто отбрасываться
  }
  unsigned long currentMillis = millis();
  while (millis() - currentMillis < intervalVision) {
    FastLED.show();
    int cursor = 21; //65
    //    float t = RTC.temperature();
    int celsius = temperatureOutdoor;
    for (int i = 1; i <= 2; i++) {

      int digit = celsius % 10; // get last digit in time
      if (i == 1) {

        for (int k = 0; k <= 20; k++) {

          if (digits[digit][k] == 1) {
            leds[cursor] = tempLedColor;
          }

          else if (digits[digit][k] == 0) {
            leds[cursor] = 0x000000;
          };

          cursor ++;

        }; // fin for

        FastLED.show();

      }// fin if

      else if (i == 2) {

        cursor = 0;

        for (int k = 0; k <= 20; k++) {

          if (digits[digit][k] == 1) {
            leds[cursor] = tempLedColor;
          }

          else if (digits[digit][k] == 0) {
            leds[cursor] = 0x000000;
          };

          cursor ++;

        };
      }

      celsius /= 10;
      FastLED.show();
    }
    for (int m = 44; m < 56; m++) {
      leds[m] = tempLedColor;
    }
    for (int m = 72; m < 83; m++) {
      leds[m] = tempLedColor;
    }
    FastLED.show();
    //check_for_input();
  }//fin while animate
}

//пока не используется
void check_for_input() {
  if (animation_change_timeout > 100) {
    if (Serial.available() > 0) {
      // read the incoming byte:
      incoming_command = Serial.read();
      // say what you got:
      Serial.print("I received: ");
      Serial.println(incoming_command);
      animate = false;
    }
  }
}

void BuzzerSound() {
    int Now = GetTime(); // Получить время
//  Serial.println (sec);
  for (int p = 0; p <= 7; p++) { // перебор массива данных времени
    int value = signalRabDay [p];
//    Serial.print ("value= ");
//    Serial.println (value);
//    Serial.print ("Now= ");
//    Serial.println (Now);
//    
    if ( value == Now ) {
      unsigned long currentMillis = millis();
      while (millis() - currentMillis < intervalSong) {
         Flag_1 = true;       //если есть совпадение по массиву поднимаем флаг на период intervalSong
            }
    }
    }
//  Serial.print ("Flag_1 ");
//  Serial.println (Flag_1);

  if (sec <= 3) Flag_2 = true;    //поднимаем флаг_2 на 3 секунды в начале каждой минуты, тем самым задаем продолжительность звучания сигнала
  else if (sec > 3) { 
  Flag_1 = false;
  Flag_2 = false;
  }
//  Serial.print ("Flag_2 ");
//  Serial.println (Flag_2);
  
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis1 > IMPULSE_TONE)  {
    previousMillis1 = currentMillis ;
    if (relayState == LOW) relayState = HIGH;
    else relayState = LOW;
  }
  if (Flag_1 && Flag_2) digitalWrite (BUZZER, relayState); //включаем пин реле если Флаг_1 и Флаг_2 = тру
  else if ( !Flag_1 || !Flag_2 ) {
  digitalWrite (BUZZER, LOW);     //выключаем если хотя один из флагов опущен
  relayState = LOW;
  }
}
  
void loop() {
  BrightnessCheck(); // Check brightness
  TimeToArray(); // Получить массив светодиодов с необходимой конфигурацией
  if (tempTimer.isReady())
    TempOutdoor();
  if (dateTimer.isReady())
    DateToArray();
  BuzzerSound();
  IR_Check();
  FastLED.show(); // Показать массив светодиодов
}

Здравствуйте! Прошу помощи добрые люди. Имеем часы на адресной светодиодной ленте с выводом даты и температурой на улице. Необходимо прикрутить оповещатель срабатывающий в определенное время заданное массивом signalRabDay. И тут вот никак не могу сообразить каким образом при условии сработки одного из элементов массива в течении 3 секунд должна  подача высокого уровня на пин реле D2, при этом чтобы сигнал звучал прерывисто с частотой 2 Герц. Моя интерпретация алгоритма в скетче заключена в функции BuzzerSound(). Строки с 635 по 674. Иногда срабатывает как нужно, иногда нет. Знаю что налепил ерунды и это можно переделать в несколько строчек. ноне знаю как. Подскажите пожалуйста.

 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

del

Bruzzer
Offline
Зарегистрирован: 17.03.2020

marat-ufa83 пишет:

 И тут вот никак не могу сообразить каким образом при условии сработки одного из элементов массива в течении 3 секунд должна  подача высокого уровня на пин реле D2, при этом чтобы сигнал звучал прерывисто с частотой 2 Герц.

Код длинный, скобки не выравнены - разбираться трудно.

Но почему в 647 - 649 строке вы крутитесь в цикле 3 секунды ничего не делая кроме установки флага? Фактически вы просто пропускаете 3 секунды и устанавливаете флаг.

      while (millis() - currentMillis < intervalSong) {
         Flag_1 = true;       //если есть совпадение по массиву поднимаем флаг на период intervalSong
            }

 

 
b707
Offline
Зарегистрирован: 26.05.2017

marat-ufa83 пишет:
Здравствуйте! Прошу помощи добрые люди. Имеем часы на адресной светодиодной ленте с выводом даты и температурой на улице.

О, очередная реинкарнация бессмертного кода вот из этой ветки:

http://arduino.ru/forum/programmirovanie/bolshie-nastennye-chasy-na-arduino

Марат, покопайтесь там, в ветке 14 страниц и как минимум десяток примеров работающего кода на той же основе, что у вас. Может что-то подберете для себя. Если хотите, я могу переделать часы под ваши желания. но только на платной основе. бесплатно переписывать этот код мне уже надоело, каждый новый новичок вновь приходит с исходной кривой версией. в которую еще и насажал своих ошибок.