Используйте LDR для запуска скетча

Это может показаться простым вопросом, но я пытался найти правильное решение, но все, что я нашел, это обычное мигание светодиода, и даже я могу закодировать этот самородок. Я совсем новичок в программировании на ардуино, но у меня есть рука с паяльником. Что я хотел бы сделать, так это объединить атрибуты LDR, чтобы позволить скетчу освещения работать в темноте и отключаться при дневном свете, но все, что я, кажется, нахожу, это повернуть контакт вверх или вниз, это бесполезно, поскольку я уже есть скетч, который я хотел бы запустить

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

Спасибо Дэйв

, 👍-2

Обсуждение

Можете ли вы показать нам написанный вами скетч «освещения»?, @VE7JRO

Похоже, вам нужно поместить свой световой код в оператор if, который проверяет уровень освещенности. Я знаю, что видел этот проект снова и снова, поэтому я не верю, что вы не можете найти пример. Если вы найдете тот, который просто устанавливает пин в высокое или низкое положение в ответ на ldr, то вы почти у цели. Просто удалите линию, которая включает или выключает контакт, и замените его кодом, который включает или выключает светодиодную ленту. Это действительно так просто., @Delta_G

функция, которая считывает значение LDR, и функция, которая включает свет, — это две совершенно разные функции... функция LDR поднимает флаг с надписью "включен свет"... больше ничего не делает.... свет функция включает свет, если она видит флаг .... больше ничего не делает .... флаг «включение света» также может быть поднят нажатием кнопки, таймером или звуковым детектором, слышимым шумом и т. д., @jsotola


2 ответа


2

Вряд ли вы найдете именно то, что вам нужно, в виде существующего примера кода. Разбейте его на части и решите по частям.

Вы не можете "Выполнить скетч" на основе чтения значения LDR. Вы можете написать новый скетч, который считывает LDR и вызывает функцию, если темно, или другую функцию, если светло. Вам нужно будет преобразовать код из вашего другого скетча в функции, которые вы сможете интегрировать в свой новый комбинированный скетч, использующий LDR. Это означает, что нужно делать оригинальное программирование, а не «находить правильное решение». готовые в Интернете.

Во-первых, как с помощью LDR определить, светлое оно или темное? Ответ, используйте аналоговый вход. Создайте делитель напряжения с LDR и резистором аналогичного размера и подайте выход на аналоговый вывод. Скажем, LDR находится между +5 В и выводом, поэтому большее количество света приводит к более высокому напряжению и, следовательно, к большему значению.

Запишите выходные данные LDR на консоль в цикле и определите пороговые значения для светлого и темного. Сделайте пороговое значение постоянным. Назовем его ТЕМНЫМ.

Теперь напишите функцию цикла. Это может выглядеть примерно так:

int lightValue;
#define ldr_pin xxx //ваш вывод
#define threshold xxx //ваше пороговое значение

void setup() {
   // устанавливаем вывод ldr как аналоговый вход
}

void loop() {
   lightValue = analogRead(ldr_pin);
   if (lightValue <= threshold) {
      doNightStuff();
   } else {
      stopDoingStuff();
   }
}

Изменить:

Как упомянул Эдгар, приведенный выше код подвержен "дрожанию", когда он будет быстро переключаться между темным и светлым состояниями.

Решение состоит в том, чтобы добавить буферный диапазон, в котором, находясь в одном состоянии, он не меняет состояния, пока не покинет буферный диапазон.

Инструкция if может выглядеть следующим образом:

#define buffer 5

if ((lightValue +buffer) <= threshold) 
    doNightStuff(); 
else if ((lightValue -buffer) >= threshold) 
    stopDoingStuff(); 
    
,

Еще лучше было бы с двумя порогами, дающими некоторый гистерезис., @Edgar Bonet

Справедливое замечание, но я думаю, что это может быть за пределами текущего уровня понимания ОП., @Duncan C

Вы, наверное, правы. OTOH, без гистерезиса, ОП, вероятно, вернется сюда довольно скоро. :-), @Edgar Bonet

если вы подключаете LDR к контакту INPUT_PULLUP вместо VIN, вам не нужен постоянный резистор для формирования делителя, просто подключите другой вывод LDR к аналоговому входу. Это не даст вам полного диапазона, но разрешения более чем достаточно, чтобы отличить темное от светлого., @dandavis

простое добавление гистерезиса, замена всего кода цикла, кроме первой строки: if ((lightValue +5) <= threshold) doNightStuff(); if ((lightValue -5) >= threshold) stopDoingStuff(); При необходимости отрегулируйте., @dandavis


-1

@ Дункан С

думаю, у меня есть решение, не уверен, подойдет ли оно вам, но оно работает, так что неплохо для новичка, лол

//
// "Пацифика"
// Нежные, сине-зеленые океанские волны.
// Декабрь 2019 г., Марк Кригсман и Мэри Кори Марч.
// Для Дэна.
// Спасибо за набросок, я добавил датчик дневного света, так что теперь они срабатывают при дневном свете. Дэйв Коуэлл, июнь 2020 г.

int lightValue;  // новый код постоянного тока

#define FASTLED_ALLOW_INTERRUPTS 0
#include <FastLED.h>
FASTLED_USING_NAMESPACE


#define ldr_pin             A0   //новый постоянный ток
#define Threshold_dark      100  //новый DC
#define Threshold_light     1000  //новый постоянный ток
#define DATA_PIN            7
#define NUM_LEDS            28
#define MAX_POWER_MILLIAMPS 500
#define LED_TYPE            WS2811
#define COLOR_ORDER         RGB

////////////////////////////////////////////////// /////////////////////////

CRGB leds[NUM_LEDS];

void setup() {

  analogRead (A0);  // новый постоянный ток
 
  delay( 3000); // 3-секундная задержка для восстановления загрузки и минута тишины
  FastLED.addLeds<LED_TYPE,DATA_PIN,COLOR_ORDER>(leds, NUM_LEDS)
        .setCorrection( TypicalLEDStrip );
  FastLED.setMaxPowerInVoltsAndMilliamps( 5, MAX_POWER_MILLIAMPS);
}

void loop(){

 lightValue = analogRead (ldr_pin);  // новый постоянный ток

 if (lightValue <= Threshold_dark){    // новый DC

    EVERY_N_MILLISECONDS(20)     
    pacifica_loop();
    FastLED.show();
  
 }else { (lightValue = Threshold_light);  // Новый DC

 {                                         // Новый DC

 for (int i = 0; i <NUM_LEDS;i++){         // Новый DC

      memset (leds,0,NUM_LEDS*3);          // Новый DC

 
                FastLED.show();             // Новый DC

                FastLED.delay (100);         // Новый DC

 }         // Новый DC
  }        // Новый DC
   }       // Новый DC
    }      // Новый DC



 
////////////////////////////////////////////////// /////////////////////////
//
// Код этой анимации сложнее, чем в других примерах, и
// хотя он "готов к запуску" и в целом задокументирован, он, вероятно, не
// лучшая отправная точка для обучения. Тем не менее он иллюстрирует некоторые
// полезные приемы.
//
////////////////////////////////////////////////// /////////////////////////
//
// В этой анимации есть четыре "слоя" волн света.
//
// Каждый слой перемещается независимо, и каждый масштабируется отдельно.
//
// Все четыре волновых слоя складываются друг над другом, а затем
// применяется другой фильтр, добавляющий "белые шапки" яркости, где
// волны больше совпадают друг с другом. Наконец, сделан еще один проход
// над массивом светодиодов, чтобы «углубить» (приглушить) синие и зеленые оттенки.
//
// Скорость, масштаб и движение каждого слоя медленно изменяются в пределах независимого
// выбранные вручную диапазоны, поэтому в коде много низкоскоростных функций beatsin8
// с большим количеством странно специфичных числовых диапазонов.
//
// Эти три пользовательские сине-зеленые цветовые палитры были вдохновлены цветами из
// воды у южного побережья Калифорнии, https://goo.gl/maps/QQgd97jjHesHZVxQ7
//
CRGBPalette16 pacifica_palette_1 = 
    { 0x000507, 0x000409, 0x00030B, 0x00030D, 0x000210, 0x000212, 0x000114, 0x000117, 
      0x000019, 0x00001C, 0x000026, 0x000031, 0x00003B, 0x000046, 0x14554B, 0x28AA50 };
CRGBPalette16 pacifica_palette_2 = 
    { 0x000507, 0x000409, 0x00030B, 0x00030D, 0x000210, 0x000212, 0x000114, 0x000117, 
      0x000019, 0x00001C, 0x000026, 0x000031, 0x00003B, 0x000046, 0x0C5F52, 0x19BE5F };
CRGBPalette16 pacifica_palette_3 = 
    { 0x000208, 0x00030E, 0x000514, 0x00061A, 0x000820, 0x000927, 0x000B2D, 0x000C33, 
      0x000E39, 0x001040, 0x001450, 0x001860, 0x001C70, 0x002080, 0x1040BF, 0x2060FF };


void pacifica_loop()
{
  // Увеличить четыре "начала индекса цвета" счетчики, по одному на каждый волновой слой.
  // Каждое значение увеличивается с разной скоростью, и скорости меняются со временем.
  static uint16_t sCIStart1, sCIStart2, sCIStart3, sCIStart4;
  static uint32_t sLastms = 0;
  uint32_t ms = GET_MILLIS();
  uint32_t deltams = ms - sLastms;
  sLastms = ms;
  uint16_t speedfactor1 = beatsin16(3, 179, 269);
  uint16_t speedfactor2 = beatsin16(4, 179, 269);
  uint32_t deltams1 = (deltams * speedfactor1) / 256;
  uint32_t deltams2 = (deltams * speedfactor2) / 256;
  uint32_t deltams21 = (deltams1 + deltams2) / 2;
  sCIStart1 += (deltams1 * beatsin88(1011,10,13));
  sCIStart2 -= (deltams21 * beatsin88(777,8,11));
  sCIStart3 -= (deltams1 * beatsin88(501,5,7));
  sCIStart4 -= (deltams2 * beatsin88(257,4,6));

  // Очистить светодиодную матрицу до тусклого сине-зеленого фона
  fill_solid( leds, NUM_LEDS, CRGB( 2, 6, 10));

  // Рендерим каждый из четырех слоев с разными масштабами и скоростями, которые меняются со временем
  pacifica_one_layer( pacifica_palette_1, sCIStart1, beatsin16( 3, 11 * 256, 14 * 256), beatsin8( 10, 70, 130), 0-beat16( 301) );
  pacifica_one_layer( pacifica_palette_2, sCIStart2, beatsin16( 4,  6 * 256,  9 * 256), beatsin8( 17, 40,  80), beat16( 401) );
  pacifica_one_layer( pacifica_palette_3, sCIStart3, 6 * 256, beatsin8( 9, 10,38), 0-beat16(503));
  pacifica_one_layer( pacifica_palette_3, sCIStart4, 5 * 256, beatsin8( 8, 10,28), beat16(601));

  // Добавляем более яркие «белые шапки» там, где волны больше выстраиваются в линию
  pacifica_add_whitecaps();

  // Немного углубляем блюз и зелень
  pacifica_deepen_colors();
}

// Добавляем один слой волн в массив светодиодов
void pacifica_one_layer( CRGBPalette16 & p, uint16_t cistart, uint16_t wavescale, uint8_t bri, uint16_t ioff)
{
  uint16_t ci = cistart;
  uint16_t waveangle = ioff;
  uint16_t wavescale_half = (wavescale / 2) + 20;
  for( uint16_t i = 0; i < NUM_LEDS; i++) {
    waveangle += 250;
    uint16_t s16 = sin16( waveangle ) + 32768;
    uint16_t cs = scale16( s16 , wavescale_half ) + wavescale_half;
    ci += cs;
    uint16_t sindex16 = sin16( ci) + 32768;
    uint8_t sindex8 = scale16( sindex16, 240);
    CRGB c = ColorFromPalette( p, sindex8, bri, LINEARBLEND);
    leds[i] += c;
  }
}

// Добавляем дополнительный «белый» в области, где четыре слоя света ярко выстроились в линию
void pacifica_add_whitecaps()
{
  uint8_t basethreshold = beatsin8( 9, 55, 65);
  uint8_t wave = beat8( 7 );
  
  for( uint16_t i = 0; i < NUM_LEDS; i++) {
    uint8_t threshold = scale8( sin8( wave), 20) + basethreshold;
    wave += 7;
    uint8_t l = leds[i].getAverageLight();
    if( l > threshold) {
      uint8_t overage = l - threshold;
      uint8_t overage2 = qadd8( overage, overage);
      leds[i] += CRGB( overage, overage2, qadd8( overage2, overage2));
    }
  }
}

// Углубляем блюз и зелень
void pacifica_deepen_colors()
{
  for( uint16_t i = 0; i < NUM_LEDS; i++) {
    leds[i].blue = scale8( leds[i].blue,  145); 
    leds[i].green= scale8( leds[i].green, 200); 
    leds[i] |= CRGB( 2, 5, 7);
  }
  {

  }
}
,