DMX приемник + Диммер на Ардуино. Вместе не хочет работать

greylight2
Offline
Зарегистрирован: 19.11.2017

Есть два скетча найденные в сети:

1. DMX-приемник

// - - - - -
// DmxSerial - A hardware supported interface to DMX.
// DmxSerialRecv.ino: Sample DMX application for retrieving 3 DMX values:
// address 1 (red) -> PWM Port 9
// address 2 (green) -> PWM Port 6
// address 3 (blue) -> PWM Port 5
// 
// Copyright (c) 2011-2015 by Matthias Hertel, http://www.mathertel.de
// This work is licensed under a BSD style license. See http://www.mathertel.de/License.aspx
// 
// Documentation and samples are available at http://www.mathertel.de/Arduino
// 25.07.2011 creation of the DmxSerial library.
// 10.09.2011 fully control the serial hardware register
//            without using the Arduino Serial (HardwareSerial) class to avoid ISR implementation conflicts.
// 01.12.2011 include file and extension changed to work with the Arduino 1.0 environment
// 28.12.2011 changed to channels 1..3 (RGB) for compatibility with the DmxSerialSend sample.
// 10.05.2012 added some lines to loop to show how to fall back to a default color when no data was received since some time.
// - - - - -

#include <DMXSerial.h>

// Constants for demo program

const int RedPin =    9;  // PWM output pin for Red Light.
//const int GreenPin =  6;  // PWM output pin for Green Light.
//const int BluePin =   5;  // PWM output pin for Blue Light.

#define RedDefaultLevel   100
//#define GreenDefaultLevel 200
//#define BlueDefaultLevel  255

void setup () {
  DMXSerial.init(DMXReceiver);
  
  // set some default values
  DMXSerial.write(1, 80);
  DMXSerial.write(2, 0);
  DMXSerial.write(3, 0);
  
  // enable pwm outputs
  pinMode(RedPin,   OUTPUT); // sets the digital pin as output
//  pinMode(GreenPin, OUTPUT);
 // pinMode(BluePin,  OUTPUT);
}


void loop() {
  // Calculate how long no data backet was received
  unsigned long lastPacket = DMXSerial.noDataSince();
  
  if (lastPacket < 5000) {
    // read recent DMX values and set pwm levels 
  //  analogWrite(RedPin, DMXSerial.read(1));
//    analogWrite(GreenPin, DMXSerial.read(2));
//    analogWrite(BluePin,  DMXSerial.read(3));

  } else {
    // Show pure red color, when no data was received since 5 seconds or more.
    analogWrite(RedPin,   RedDefaultLevel);
//    analogWrite(GreenPin, GreenDefaultLevel);
//    analogWrite(BluePin,  BlueDefaultLevel);
  } // if
}

// End.

2. Многоканальный диммер

#include <TimerOne.h>
volatile uint8_t tic ;
uint8_t data;
int startDimPin = 3; //первый диммер
int endDimPin = 6; //последний диммер
int Dimmer[3]; //количество диммеров минус 1

void setup() {


  //*********************Настраиваем порты на выход**********************

  for ( int i = startDimPin; i <= endDimPin; i++) //пройдемся циклом по портам
  {
    pinMode (i, OUTPUT);
    digitalWrite(i, LOW); // гасим оответствующий пин

    Dimmer[i - startDimPin] = 10; //выставим яркость соответствующего диммера в 0
  }
  //CHANGE – прерывание вызывается при любом изменении значения на входе;
  //RISING – вызов прерывания при изменении уровня напряжения с низкого (Low) на высокий(HIGH)
  //FALLING – вызов прерывания при изменении уровня напряжения с высокого (HIGH) на низкий (Low)
  attachInterrupt(0, detect_up, LOW);  // настроить срабатывание прерывания interrupt0 на pin 2 на низкий уровень
  Timer1.initialize(40);              // Интервал срабатывания таймера в мкс
  Timer1.attachInterrupt(halfcycle);   //будет вызыватся каждый раз при отсчете заданого времени
  Timer1.stop();
  Serial.begin(115200); //инициализация порта
  randomSeed(analogRead(0)); //псевдогенератор случайных чисел будет использовать шумы на аналог пин 0
}

//********************обработчики прерываний*******************************
void halfcycle()  //прерывания таймера
{
  tic--;  //счетчик
  for ( int i = startDimPin; i <= endDimPin; i++)
  {
    if (Dimmer[i - startDimPin] > tic )
      digitalWrite(i, HIGH); //управляем выходом (откроем семистор)
  }
}

void  detect_up()  // обработка внешнего прерывания. Сработает по переднему фронту
{
  tic = 200;           //обнулить счетчик
  Timer1.resume();   //запустить таймер
  attachInterrupt(0, detect_down, HIGH);  //перепрограммировать прерывание на другой обработчик
}

void  detect_down()  // обработка внешнего прерывания. Сработает по заднему фронту
{
  Timer1.stop(); //остановить таймер
  for ( int i = startDimPin; i <= endDimPin; i++)
  {

    digitalWrite(i, LOW);
  }
  tic = 200;     //обнулить счетчик
  attachInterrupt(0, detect_up, LOW); //перепрограммировать прерывание на другой обработчик

}

void loop() {
  

//********помигаем первым диммером рандомно********
    Dimmer[0] = random(10, 200);
    //Задержка для более плавного эффекта мерцания
    delay(1000);
}  

Для начала я их протестировал на работоспособность каждый по отдельности. Всё работает как надо!

Но когда я пытаюсь их объединить в один скетч, начинаются непонятки.

Вот объединенный и немного упрощенный код:

#include <TimerOne.h>
#include <DMXSerial.h>

////////////////////////////////////////////////////////////////
volatile uint8_t tic ;
uint8_t data;
int startDimPin = 3; //первый диммер
int endDimPin = 6; //последний диммер
int Dimmer[3]; //количество диммеров минус 1
/////////////////////////////////////////////////////////////////

 #define RedDefaultLevel   100

void setup() {
 
//*********************Настраиваем порты на выход**********************

  for ( int i = startDimPin; i <= endDimPin; i++) //пройдемся циклом по портам
  {
    pinMode (i, OUTPUT);
    digitalWrite(i, LOW); // гасим оответствующий пин

    Dimmer[i - startDimPin] = 10; //выставим яркость соответствующего диммера в 0
  }
  //CHANGE – прерывание вызывается при любом изменении значения на входе;
  //RISING – вызов прерывания при изменении уровня напряжения с низкого (Low) на высокий(HIGH)
  //FALLING – вызов прерывания при изменении уровня напряжения с высокого (HIGH) на низкий (Low)

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

  attachInterrupt(0, detect_up, LOW);  // настроить срабатывание прерывания interrupt0 на pin 2 на низкий уровень
  Timer1.initialize(40);              // Интервал срабатывания таймера в мкс
  Timer1.attachInterrupt(halfcycle);   //будет вызыватся каждый раз при отсчете заданого времени
  Timer1.stop();
//  Serial.begin(115200); //инициализация порта
  randomSeed(analogRead(0)); //псевдогенератор случайных чисел будет использовать шумы на аналог пин 0

////////////////////////////////////////////////////////////////  
  DMXSerial.init(DMXReceiver);
  
  DMXSerial.write(1, 80);
  DMXSerial.write(2, 0);
  DMXSerial.write(3, 0);
/////////////////////////////////////////////////////////////////  
  
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////
//********************обработчики прерываний*******************************
void halfcycle()  //прерывания таймера
{
  tic--;  //счетчик
  for ( int i = startDimPin; i <= endDimPin; i++)
  {
    if (Dimmer[i - startDimPin] > tic )
      digitalWrite(i, HIGH); //управляем выходом (откроем семистор)
  }
}

void  detect_up()  // обработка внешнего прерывания. Сработает по переднему фронту
{
  tic = 200;           //обнулить счетчик
  Timer1.resume();   //запустить таймер
  attachInterrupt(0, detect_down, HIGH);  //перепрограммировать прерывание на другой обработчик
}


void  detect_down()  // обработка внешнего прерывания. Сработает по заднему фронту
{
  Timer1.stop(); //остановить таймер
  for ( int i = startDimPin; i <= endDimPin; i++)
  {

    digitalWrite(i, LOW);
  }
  tic = 200;     //обнулить счетчик
  attachInterrupt(0, detect_up, LOW); //перепрограммировать прерывание на другой обработчик

}

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

void loop() {
  
  unsigned long lastPacket = DMXSerial.noDataSince();
  
  if (lastPacket < 5000) {
   Dimmer[0] = DMXSerial.read(1);
  } else {
   analogWrite(9, 30);
    Dimmer[0] = RedDefaultLevel;
  }
} 

greylight2
Offline
Зарегистрирован: 19.11.2017

Первая проблема, которая возникла - это неудавалось загрузить скетч. Выскакивала ошибка.

Проблема решилась комментированием строки:
 

//  Serial.begin(115200); //инициализация порта

 

Затем обнаружилось, что не работает DMX приемник. Перебрав разные варианты, проблема решилась комментированием внутри setup строки:

//  Timer1.stop();

 Но при этом появилась следующая проблема)))  Диммер перестал рандомно менять яркость. Вместо этого яркость стала максимальной.

Замечено, что на эту проблему влияет комментирование строки:

DMXSerial.init(DMXReceiver);

Есть подозрение, что конфликтует код в подключенных библиотеках.

В этом я к сожалению не силен. Нужна ваша помощь!

Ссылки на библиотеки : https://yadi.sk/d/45JdviVi3Pq3A6

 

Penni
Penni аватар
Offline
Зарегистрирован: 18.01.2015

ну как минимум

attachInterrupt(0, detect_up, LOW);  // настроить срабатывание прерывания interrupt0 на pin 2 на низкий уровень

и это из DMXSerial.h

#define DMXMODEPIN 2     ///< Arduino pin 2 for controlling the data direction is the default value.

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

Catholic
Offline
Зарегистрирован: 02.01.2015

Может, это поможет? http://city416.ru/prj/dmx_led2.html

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

Ты, что, методом тыка всё подряд комментируешь?

greylight2
Offline
Зарегистрирован: 19.11.2017

Получается что, да ))

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

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

greylight2 пишет:

Когда не хватает знаний, а хочется чтобы вот уже сейчас начало работать...

Если для Вас "нет ошибок компиляции" и "работает" - одно и то же, закомментируйте все строки.

Цитата:

Потому что выучить и понимать всё сразу довольно проблематично.

ТОгда начните с мигания светодиодом. Т.е. с таких задач, которые можете написать самостоятельно, и только потом постепенно усложняйте.

greylight2
Offline
Зарегистрирован: 19.11.2017

andriano пишет:

ТОгда начните с мигания светодиодом. Т.е. с таких задач, которые можете написать самостоятельно, и только потом постепенно усложняйте.

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

И прошу вас тему делитантства в программировании больше не развивать.... Эта тема стара как мир!

Кто может помочь, помогите. Кто не может, молча пройдите мимо!

Тем, кто уже дал советы, СПАСИБО! Завтра начну их применять... если не смогу сам разобраться, я напишу! 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

greylight2 пишет:

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

Тогнда Вы обратились не в тот раздел. Вам нужно было создавать тему в "Ищу исполнителя".

greylight2
Offline
Зарегистрирован: 19.11.2017

Penni пишет:

ну как минимум

attachInterrupt(0, detect_up, LOW);  // настроить срабатывание прерывания interrupt0 на pin 2 на низкий уровень

и это из DMXSerial.h

#define DMXMODEPIN 2     ///< Arduino pin 2 for controlling the data direction is the default value.

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

Переписал в скетче везде attachInterrupt на 3 пин и всё заработало!!!!

Может конечно еще где-то что-то надо исправлять, но пока так...

Всем спасибо!