Синхронная работа 8 Ардуино мигание диодов в секундах

Олег911
Offline
Зарегистрирован: 18.10.2020

Есть такой проект, через радиомодуль подаётся сигнал на 8 ардуино, и они должны работать по прописанному коду синхронно включать выключать диоды на костюмах ws2812b. Часы реального времени дают задержку каждые 5 секунд. Пытались менять код и mills и delay. Но разсрнхронизация все равно есть. Сначала диоды загораются при подаче сигнала синхронно. Но в процессе кода начинаются сбои и рассинхрон. В чем может быть проблема ? Ардуино итальянское не китайское. Думаю перейти на esp32 или nodemcu на базе eap8266 и через mqtt протокол запустить все 8 костюмов. Но в esp вообще не разбираюсь. Кто то вообще  сталкивался с синхронной работой ардуино от 5 шт. Код прописан по секундам.

Олег911
Offline
Зарегистрирован: 18.10.2020

Если кто знает как решить этот вопрос готов заплатить 

MaksVV
Offline
Зарегистрирован: 06.08.2015

Стандартный встречный вопрос. А где код, схема подключения? 

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

Олег911
Offline
Зарегистрирован: 18.10.2020
#include <Adafruit_NeoPixel.h>
#include "VirtualWire.h"
byte message[VW_MAX_MESSAGE_LEN]; // Буфер для хранения принимаемых данных
byte messageLength = VW_MAX_MESSAGE_LEN; // Размер сообщения

const int receiver_pin = 12; // Пин подключения приемника

#define PIN 6
#define count_led 8 // количество светодиодов 
// 4 - leg right 2 led
// 5 - leg left 2 led
// 6 - top right side 4 led
// 7 - top left side 4 led
// 8 - center 3 led
Adafruit_NeoPixel legRight = Adafruit_NeoPixel(2, 4, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel legLeft = Adafruit_NeoPixel(2, 5, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel topLeft = Adafruit_NeoPixel(4, 6, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel topRight = Adafruit_NeoPixel(4, 7, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel center = Adafruit_NeoPixel(3, 8, NEO_GRB + NEO_KHZ800);
void setup() {
  vw_set_rx_pin(receiver_pin); // Пин подключения приемника
  pinMode(13, OUTPUT);
  vw_setup(2000); // Скорость передачи данных (бит в секунду)
  vw_rx_start(); // Активация применика
  legRight.begin();
  legRight.show(); // Initialize all pixels to 'off'
  legLeft.begin();
  legLeft.show(); // Initialize all pixels to 'off'
  topRight.begin();
  topRight.show(); // Initialize all pixels to 'off'
  topLeft.begin();
  topLeft.show(); // Initialize all pixels to 'off'
  center.begin();
  center.show(); // Initialize all pixels to 'off'  dance();

}
void loop() {
  // Some example procedures showing how to display to the pixels:
  if (vw_get_message(message, &messageLength)) // Если есть данные..
  {
    if (message[0] == 'H')
    {
      digitalWrite(13, HIGH);
      dance();// включение по радио
    }
  }
}


int key1 = true;
int key2 = true;
int key3 = true;
int key4 = true;
int key5 = true;
int key6 = true;
int key7 = true;
int key8 = true;
int key9 = true;
int key10 = true;
int key11 = true;
int key12 = true;
int key13 = true;
int key14 = true;
int key15 = true;
int key16 = true;
int key17 = true;
int key18 = true;
int key19 = true;
int key20 = true;
int key21 = true;
int key22 = true;
int key23 = true;
int key24 = true;
int key25 = true;
int key26 = true;
int key27 = true;
int key28 = true;
int key29 = true;
int key30 = true;
int key31 = true;
int key32 = true;
int key33 = true;
int key34 = true;
int key35 = true;
int key36 = true;
int key37 = true;
int key38 = true;
int key39 = true;
int key40 = true;
int key41 = true;
int key42 = true;
int key43 = true;
int key44 = true;
int key45 = true;
int key46 = true;
int key47 = true;
int key48 = true;
int key49 = true;
int key50 = true;
int key51 = true;
int key52 = true;
int key53 = true;
int key54 = true;
int key55 = true;
int key56 = true;
int key57 = true;
int key58 = true;
int key59 = true;
int key60 = true;
int key61 = true;
int key62 = true;
int key63 = true;
int key64 = true;
int key65 = true;
int key66 = true;
int key67 = true;
int key68 = true;
int key69 = true;
int key70 = true;
int key71 = true;
int key72 = true;
int key73 = true;
int key74 = true;
int key75 = true;
int key76 = true;
int key77 = true;
int key78 = true;
int key79 = true;
int key80 = true;
int key81 = true;
int key82 = true;
int key83 = true;
int key84 = true;
int key85 = true;
int key86 = true;
int key87 = true;
int key88 = true;
int key89 = true;
int key90 = true;
int key91 = true;
int key92 = true;
int key93 = true;
int key94 = true;
int key95 = true;
int key96 = true;
int key97 = true;
int key98 = true;
int key99 = true;
int key100 = true;
int key101 = true;
int key102 = true;
int key103 = true;
int key104 = true;
int key105 = true;
int key106 = true;
int key107 = true;
int key108 = true;
int key109 = true;
int key110 = true;
int key111 = true;
int key112 = true;
int key113 = true;
int key114 = true;
int key115 = true;
int key116 = true;
int key117 = true;
int key118 = true;
int key119 = true;
int key120 = true;
int key121 = true;
int key122 = true;
int key123 = true;
int key124 = true;
int key125 = true;
int key126 = true;
int key127 = true;
int key128 = true;
int key129 = true;
int key130 = true;
int key131 = true;
int key132 = true;
int key133 = true;
int key134 = true;
int key135 = true;
void dance()
{
  //
  unsigned long myStartTime = millis();
  while (true)
  {
    unsigned long correctTime = millis();

      if (key1)
    {
      if (correctTime - myStartTime >= 100) // время в мс ( 1 сек = 1000 мс)
      {
        center.setPixelColor(0, center.Color(0, 255, 0)); // Moderately bright green color.
        center.setPixelColor(1, center.Color(0, 255, 0)); // Moderately bright green color.
        center.setPixelColor(2, center.Color(0, 255, 0)); // Moderately bright green color.
        center.show();
        topRight.setPixelColor(0, topRight.Color(0, 255, 0)); // Moderately bright green color.
        topRight.setPixelColor(1, topRight.Color(0, 255, 0)); // Moderately bright green color.
        topRight.setPixelColor(2, topRight.Color(0, 255, 0)); // Moderately bright green color.
        topRight.setPixelColor(3, topRight.Color(0, 255, 0)); // Moderately bright green color.
        topRight.show();
        topLeft.setPixelColor(0, topLeft.Color(0, 255, 0)); // Moderately bright green color.
        topLeft.setPixelColor(1, topLeft.Color(0, 255, 0)); // Moderately bright green color.
        topLeft.setPixelColor(2, topLeft.Color(0, 255, 0)); // Moderately bright green color.
        topLeft.setPixelColor(3, topLeft.Color(0, 255, 0)); // Moderately bright green color.
        topLeft.show();
        legRight.setPixelColor(0, legRight.Color(0, 255, 0)); // Moderately bright green color.
        legRight.setPixelColor(1, legRight.Color(0, 255, 0)); // Moderately bright green color.
        legRight.show();
        legLeft.setPixelColor(0, legLeft.Color(0, 255, 0)); // Moderately bright green color.
        legLeft.setPixelColor(1, legLeft.Color(0, 255, 0)); // Moderately bright green color.
        legLeft.show();
        key1 = false;
      }
    }
    
    if (key2)
    {
      if (correctTime - myStartTime >= 5000) // время в мс ( 1 сек = 1000 мс)
      {
        center.setPixelColor(0, center.Color(0, 0, 0)); // Moderately bright green color.
        center.setPixelColor(1, center.Color(0, 0, 0)); // Moderately bright green color.
        center.setPixelColor(2, center.Color(0, 0, 0)); // Moderately bright green color.
        center.show();
        topRight.setPixelColor(0, topRight.Color(0, 0, 0)); // Moderately bright green color.
        topRight.setPixelColor(1, topRight.Color(0, 0, 0)); // Moderately bright green color.
        topRight.setPixelColor(2, topRight.Color(0, 0, 0)); // Moderately bright green color.
        topRight.setPixelColor(3, topRight.Color(0, 0, 0)); // Moderately bright green color.
        topRight.show();
        topLeft.setPixelColor(0, topLeft.Color(0, 0, 0)); // Moderately bright green color.
        topLeft.setPixelColor(1, topLeft.Color(0, 0, 0)); // Moderately bright green color.
        topLeft.setPixelColor(2, topLeft.Color(0, 0, 0)); // Moderately bright green color.
        topLeft.setPixelColor(3, topLeft.Color(0, 0, 0)); // Moderately bright green color.
        topLeft.show();
        legRight.setPixelColor(0, legRight.Color(0, 0, 0)); // Moderately bright green color.
        legRight.setPixelColor(1, legRight.Color(0, 0, 0)); // Moderately bright green color.
        legRight.show();
        legLeft.setPixelColor(0, legLeft.Color(0, 0, 0)); // Moderately bright green color.
        legLeft.setPixelColor(1, legLeft.Color(0, 0, 0)); // Moderately bright green color.
        legLeft.show();
        key2 = false;
      }
    }
    
    if (key3)
    {
      if (correctTime - myStartTime >= 10000) // время в мс ( 1 сек = 1000 мс)
      {
        center.setPixelColor(0, center.Color(0, 0, 255)); // Moderately bright green color.
        center.setPixelColor(1, center.Color(255, 0, 0)); // Moderately bright green color.
        center.setPixelColor(2, center.Color(0, 0, 255)); // Moderately bright green color.
        center.show();
        key3 = false;
      }
    }
    
    if (key4)
    {
      if (correctTime - myStartTime >= 13000) // время в мс ( 1 сек = 1000 мс)
      {
        topRight.setPixelColor(3, topRight.Color(0, 0, 255)); // Moderately bright green color.
        topRight.show();
        topLeft.setPixelColor(3, topLeft.Color(0, 0, 255)); // Moderately bright green color.
        topLeft.show();
        legRight.setPixelColor(1, legRight.Color(0, 0, 255)); // Moderately bright green color.
        legRight.show();
        legLeft.setPixelColor(1, legLeft.Color(0, 0, 255)); // Moderately bright green color.
        legLeft.show();
        key4 = false;
      }
    }
    
    if (key5)
    {
      if (correctTime - myStartTime >= 21800) // время в мс ( 1 сек = 1000 мс)
      {
        legRight.setPixelColor(1, legRight.Color(0, 0, 255)); // Moderately bright green color.
        legRight.show();
        legLeft.setPixelColor(1, legLeft.Color(0, 0, 255)); // Moderately bright green color.
        legLeft.show();
        key5 = false;
      }
    }
    
    if (key6)
    {
      if (correctTime - myStartTime >= 22000) // время в мс ( 1 сек = 1000 мс)
      {
        legRight.setPixelColor(0, legRight.Color(0, 255, 0)); // Moderately bright green color.
        legRight.show();
        legLeft.setPixelColor(0, legLeft.Color(0, 255, 0)); // Moderately bright green color.
        legLeft.show();
        key6 = false;
      }
    }
    
    if (key7)
    {
      if (correctTime - myStartTime >= 22200) // время в мс ( 1 сек = 1000 мс)
      {
        topRight.setPixelColor(0, topRight.Color(255, 0, 0)); // Moderately bright green color.
        topRight.show();
        topLeft.setPixelColor(0, topLeft.Color(255, 0, 0)); // Moderately bright green color.
        topLeft.show();
        key7 = false;
      }
    }
    
    if (key8)
    {
      if (correctTime - myStartTime >= 22400) // время в мс ( 1 сек = 1000 мс)
      {
        topRight.setPixelColor(1, topRight.Color(0, 255, 0)); // Moderately bright green color.
        topRight.show();
        topLeft.setPixelColor(1, topLeft.Color(0, 255, 0)); // Moderately bright green color.
        topLeft.show();
        key8 = false;
      }
    }
    
    if (key9)
    {
      if (correctTime - myStartTime >= 22600) // время в мс ( 1 сек = 1000 мс)
      {
        center.setPixelColor(0, center.Color(0, 0, 255)); // Moderately bright green color.
        center.show();
        topRight.setPixelColor(2, topRight.Color(0, 255, 0)); // Moderately bright green color.
        topRight.show();
        topLeft.setPixelColor(2, topLeft.Color(0, 255, 0)); // Moderately bright green color.
        topLeft.show();
        key9 = false;
      }
    }
    
    if (key10)
    {
      if (correctTime - myStartTime >= 22800) // время в мс ( 1 сек = 1000 мс)
      {
        center.setPixelColor(1, center.Color(0, 0, 255)); // Moderately bright green color.
        center.setPixelColor(2, center.Color(255, 0, 0)); // Moderately bright green color.
        center.show();
        topRight.setPixelColor(3, topRight.Color(0, 0, 255)); // Moderately bright green color.
        topRight.show();
        topLeft.setPixelColor(3, topLeft.Color(0, 0, 255)); // Moderately bright green color.
        topLeft.show();
        key10 = false;
      }
    }
    

 

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

И где тут синхронизация?

Олег911
Offline
Зарегистрирован: 18.10.2020

Схема работы такая и есть. Только вот ардуины не мигают синхронно по заданому времени. Чем дальше идет код тем больше время разсинхрона между ними. Одна быстрее мигает другая медленее. И так каждая со постеменно в своем время мигает. Где то после 20 секунды 
Причем пробовали мигать светодиодом на самой ардуине не подключая при этом диоды. И все равно такой же разсинхрон 

sadman41
Offline
Зарегистрирован: 19.10.2016

Дак вам пока VirtualWire отложить бы в сторону и стартовать по digitalRead(2), например. Все D2 подчиненных ардуин собрать на ардуину-мастера и ею отмашку давать.

Олег911
Offline
Зарегистрирован: 18.10.2020
 
036 }
037 void loop() {
038   // Some example procedures showing how to display to the pixels:
039   if (vw_get_message(message, &messageLength)) // Если есть данные..
040   {
041     if (message[0] == 'H')
042     {
043       digitalWrite(13, HIGH);
044       dance();// включение по радио
045     }
046   }
047 }

В этот момент идет синхронное включение всех 8 ардуин через радиомодуль. А дальше просто на каждой эта программа мигает. Думал из за кварцевого резонатора но не знаю можно ли его перепаивать на самой ардуине хотя бы на те же 16 МГц которые там заложены . Читал за кварц что он имеет свойства изнашиваться. Но ардуины новые только распечатанные были.

Олег911
Offline
Зарегистрирован: 18.10.2020

Дело думая не в радиомодуле. Потому что при первом загорании они синхронно загораються, а вот потом только начинают накапливать задержки 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

так на миллисах и не пойдёт

Олег911
Offline
Зарегистрирован: 18.10.2020

адаптировать на delay тоже пробовали все равно задержка идет 

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

Судя по количеству ключей - это лишь малая часть полного кода. Код полностью длится, наверно, несколько минут?
Я правильно понял, что вся синхронизация заключается в одновременном запуске? Это ерунда.
Надо посылать синхросигналы в каждый ключевой момент танца, то есть при каждой проверке переменных key1-key135

Олег911
Offline
Зарегистрирован: 18.10.2020
#include <Adafruit_NeoPixel.h>
#include "VirtualWire.h"
byte message[VW_MAX_MESSAGE_LEN]; // Буфер для хранения принимаемых данных
byte messageLength = VW_MAX_MESSAGE_LEN; // Размер сообщения

const int receiver_pin = 12; // Пин подключения приемника

#define PIN 6
#define count_led 8 // количество светодиодов 
// 4 - leg right 2 led
// 5 - leg left 2 led
// 6 - top right side 4 led
// 7 - top left side 4 led
// 8 - center 3 led
Adafruit_NeoPixel legRight = Adafruit_NeoPixel(2, 4, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel legLeft = Adafruit_NeoPixel(2, 5, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel topLeft = Adafruit_NeoPixel(4, 6, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel topRight = Adafruit_NeoPixel(4, 7, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel center = Adafruit_NeoPixel(3, 8, NEO_GRB + NEO_KHZ800);
void setup() {
  vw_set_rx_pin(receiver_pin); // Пин подключения приемника
  pinMode(13, OUTPUT);
  vw_setup(2000); // Скорость передачи данных (бит в секунду)
  vw_rx_start(); // Активация применика
  legRight.begin();
  legRight.show(); // Initialize all pixels to 'off'
  legLeft.begin();
  legLeft.show(); // Initialize all pixels to 'off'
  topRight.begin();
  topRight.show(); // Initialize all pixels to 'off'
  topLeft.begin();
  topLeft.show(); // Initialize all pixels to 'off'
  center.begin();
  center.show(); // Initialize all pixels to 'off'  dance();

}
void loop() {
  // Some example procedures showing how to display to the pixels:
  if (vw_get_message(message, &messageLength)) // Если есть данные..
  {
    if (message[0] == 'H')
    {
      digitalWrite(13, HIGH);
      dance();// включение по радио
    }
  }
}


int key1 = true;
int key2 = true;
int key3 = true;
int key4 = true;
int key5 = true;
int key6 = true;
int key7 = true;
int key8 = true;
int key9 = true;
int key10 = true;
int key11 = true;
int key12 = true;
int key13 = true;
int key14 = true;
int key15 = true;
int key16 = true;
int key17 = true;
int key18 = true;
int key19 = true;
int key20 = true;
int key21 = true;
int key22 = true;
int key23 = true;
int key24 = true;
int key25 = true;
int key26 = true;
int key27 = true;
int key28 = true;
int key29 = true;
int key30 = true;
int key31 = true;
int key32 = true;
int key33 = true;
int key34 = true;
int key35 = true;
int key36 = true;
int key37 = true;
int key38 = true;
int key39 = true;
int key40 = true;
int key41 = true;
int key42 = true;
int key43 = true;
int key44 = true;
int key45 = true;
int key46 = true;
int key47 = true;
int key48 = true;
int key49 = true;
int key50 = true;
int key51 = true;
int key52 = true;
int key53 = true;
int key54 = true;
int key55 = true;
int key56 = true;
int key57 = true;
int key58 = true;
int key59 = true;
int key60 = true;
int key61 = true;
int key62 = true;
int key63 = true;
int key64 = true;
int key65 = true;
int key66 = true;
int key67 = true;
int key68 = true;
int key69 = true;
int key70 = true;
int key71 = true;
int key72 = true;
int key73 = true;
int key74 = true;
int key75 = true;
int key76 = true;
int key77 = true;
int key78 = true;
int key79 = true;
int key80 = true;
int key81 = true;
int key82 = true;
int key83 = true;
int key84 = true;
int key85 = true;
int key86 = true;
int key87 = true;
int key88 = true;
int key89 = true;
int key90 = true;
int key91 = true;
int key92 = true;
int key93 = true;
int key94 = true;
int key95 = true;
int key96 = true;
int key97 = true;
int key98 = true;
int key99 = true;
int key100 = true;
int key101 = true;
int key102 = true;
int key103 = true;
int key104 = true;
int key105 = true;
int key106 = true;
int key107 = true;
int key108 = true;
int key109 = true;
int key110 = true;
int key111 = true;
int key112 = true;
int key113 = true;
int key114 = true;
int key115 = true;
int key116 = true;
int key117 = true;
int key118 = true;
int key119 = true;
int key120 = true;
int key121 = true;
int key122 = true;
int key123 = true;
int key124 = true;
int key125 = true;
int key126 = true;
int key127 = true;
int key128 = true;
int key129 = true;
int key130 = true;
int key131 = true;
int key132 = true;
int key133 = true;
int key134 = true;
int key135 = true;
void dance()
{
  //
  unsigned long myStartTime = millis();
  while (true)
  {
    unsigned long correctTime = millis();


    center.setPixelColor(0, center.Color(0, 255, 0)); // Moderately bright green color.
    center.setPixelColor(1, center.Color(0, 255, 0)); // Moderately bright green color.
    center.show();
    delay(20000);
    center.setPixelColor(2, center.Color(0, 0, 255)); // Moderately bright green color.

    topRight.setPixelColor(0, topRight.Color(0, 255, 0)); // Moderately bright green color.
    topRight.setPixelColor(1, topRight.Color(0, 255, 0)); // Moderately bright green color.
    topRight.setPixelColor(2, topRight.Color(0, 255, 0)); // Moderately bright green color.
    topRight.setPixelColor(3, topRight.Color(0, 255, 0)); // Moderately bright green color.
    topRight.show();
    topLeft.setPixelColor(0, topLeft.Color(0, 255, 0)); // Moderately bright green color.
    topLeft.setPixelColor(1, topLeft.Color(0, 255, 0)); // Moderately bright green color.
    topLeft.setPixelColor(2, topLeft.Color(0, 255, 0)); // Moderately bright green color.
    topLeft.setPixelColor(3, topLeft.Color(0, 255, 0)); // Moderately bright green color.
    topLeft.show();
    legRight.setPixelColor(0, legRight.Color(0, 255, 0)); // Moderately bright green color.
    legRight.setPixelColor(1, legRight.Color(0, 255, 0)); // Moderately bright green color.
    legRight.show();
    legLeft.setPixelColor(0, legLeft.Color(0, 255, 0)); // Moderately bright green color.
    legLeft.setPixelColor(1, legLeft.Color(0, 255, 0)); // Moderately bright green color.
    legLeft.show();
    delay(40000);
    
    center.setPixelColor(0, center.Color(0, 0, 0)); // Moderately bright green color.
    center.setPixelColor(1, center.Color(0, 0, 0)); // Moderately bright green color.
    center.show();
    delay(20000);
   
    center.setPixelColor(2, center.Color(0, 0, 0)); // Moderately bright green color.
    topRight.setPixelColor(0, topRight.Color(0, 0, 0)); // Moderately bright green color.
    topRight.setPixelColor(1, topRight.Color(0, 0, 0)); // Moderately bright green color.
    topRight.setPixelColor(2, topRight.Color(0, 0, 0)); // Moderately bright green color.
    topRight.setPixelColor(3, topRight.Color(0, 0, 0)); // Moderately bright green color.
    topRight.show();
    topLeft.setPixelColor(0, topLeft.Color(0, 0, 0)); // Moderately bright green color.
    topLeft.setPixelColor(1, topLeft.Color(0, 0, 0)); // Moderately bright green color.
    topLeft.setPixelColor(2, topLeft.Color(0, 0, 0)); // Moderately bright green color.
    topLeft.setPixelColor(3, topLeft.Color(0, 0, 0)); // Moderately bright green color.
    topLeft.show();
    legRight.setPixelColor(0, legRight.Color(0, 0, 0)); // Moderately bright green color.
    legRight.setPixelColor(1, legRight.Color(0, 0, 0)); // Moderately bright green color.
    legRight.show();
    legLeft.setPixelColor(0, legLeft.Color(0, 0, 0)); // Moderately bright green color.
    legLeft.setPixelColor(1, legLeft.Color(0, 0, 0)); // Moderately bright green color.
    legLeft.show();
    delay(40000);
    
    center.setPixelColor(0, center.Color(0, 255, 0)); // Moderately bright green color.
    center.setPixelColor(1, center.Color(0, 255, 0)); // Moderately bright green color.
    center.show();
    delay(20000);
    center.setPixelColor(2, center.Color(0, 0, 255)); // Moderately bright green color.

    topRight.setPixelColor(0, topRight.Color(0, 255, 0)); // Moderately bright green color.
    topRight.setPixelColor(1, topRight.Color(0, 255, 0)); // Moderately bright green color.
    topRight.setPixelColor(2, topRight.Color(0, 255, 0)); // Moderately bright green color.
    topRight.setPixelColor(3, topRight.Color(0, 255, 0)); // Moderately bright green color.
    topRight.show();
    topLeft.setPixelColor(0, topLeft.Color(0, 255, 0)); // Moderately bright green color.
    topLeft.setPixelColor(1, topLeft.Color(0, 255, 0)); // Moderately bright green color.
    topLeft.setPixelColor(2, topLeft.Color(0, 255, 0)); // Moderately bright green color.
    topLeft.setPixelColor(3, topLeft.Color(0, 255, 0)); // Moderately bright green color.
    topLeft.show();
    legRight.setPixelColor(0, legRight.Color(0, 255, 0)); // Moderately bright green color.
    legRight.setPixelColor(1, legRight.Color(0, 255, 0)); // Moderately bright green color.
    legRight.show();
    legLeft.setPixelColor(0, legLeft.Color(0, 255, 0)); // Moderately bright green color.
    legLeft.setPixelColor(1, legLeft.Color(0, 255, 0)); // Moderately bright green color.
    legLeft.show();
    delay(40000);

    center.setPixelColor(0, center.Color(0, 0, 0)); // Moderately bright green color.
    center.setPixelColor(1, center.Color(0, 0, 0)); // Moderately bright green color.
    center.show();
    delay(20000);
   
    center.setPixelColor(2, center.Color(0, 0, 0)); // Moderately bright green color.
    topRight.setPixelColor(0, topRight.Color(0, 0, 0)); // Moderately bright green color.
    topRight.setPixelColor(1, topRight.Color(0, 0, 0)); // Moderately bright green color.
    topRight.setPixelColor(2, topRight.Color(0, 0, 0)); // Moderately bright green color.
    topRight.setPixelColor(3, topRight.Color(0, 0, 0)); // Moderately bright green color.
    topRight.show();
    topLeft.setPixelColor(0, topLeft.Color(0, 0, 0)); // Moderately bright green color.
    topLeft.setPixelColor(1, topLeft.Color(0, 0, 0)); // Moderately bright green color.
    topLeft.setPixelColor(2, topLeft.Color(0, 0, 0)); // Moderately bright green color.
    topLeft.setPixelColor(3, topLeft.Color(0, 0, 0)); // Moderately bright green color.
    topLeft.show();
    legRight.setPixelColor(0, legRight.Color(0, 0, 0)); // Moderately bright green color.
    legRight.setPixelColor(1, legRight.Color(0, 0, 0)); // Moderately bright green color.
    legRight.show();
    legLeft.setPixelColor(0, legLeft.Color(0, 0, 0)); // Moderately bright green color.
    legLeft.setPixelColor(1, legLeft.Color(0, 0, 0)); // Moderately bright green color.
    legLeft.show();
    delay(40000);
     
     }   
  }

 

Олег911
Offline
Зарегистрирован: 18.10.2020

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

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

Олег911 пишет:

Дело думая не в радиомодуле. Потому что при первом загорании они синхронно загораються, а вот потом только начинают накапливать задержки 


решение - синхросигналы каждые 2-3 секунды

sadman41
Offline
Зарегистрирован: 19.10.2016

Олег911 пишет:

Дело думая не в радиомодуле. Потому что при первом загорании они синхронно загораються, а вот потом только начинают накапливать задержки 

А вы попробуйте. Не используя и не запуская VirtualWire вовсе. Потом расскажете. 

Олег911
Offline
Зарегистрирован: 18.10.2020

А как его воплотить? ) Какая схема? 

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

Олег911 пишет:

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


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

sadman41
Offline
Зарегистрирован: 19.10.2016

b707 пишет:

Работа с адресной лентой сбивает системный таймер ардуины.

А VirtualWire сидит в ISR...

Олег911
Offline
Зарегистрирован: 18.10.2020

мы мигали светодиодом на самой ардуине  через mills и delay. Все равно был рассинхрон думал не в ленте дело. А вот синхросигнал интересно 

Олег911
Offline
Зарегистрирован: 18.10.2020

А как тогда реализовать это все? 
Только через синхросигнал? 
Извините я просто чайник вообще в этом
Можно ли VirtualWire поместить не в ISR? 

sadman41
Offline
Зарегистрирован: 19.10.2016

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

Олег911
Offline
Зарегистрирован: 18.10.2020

Прописал через delay 

#ifdef __AVR__
#include <avr/power.h>
#endif
// 4 - leg right 2 led
// 5 - leg left 2 led
// 6 - top right side 4 led
// 7 - top left side 4 led
// 8 - center 3 led
#define PIN 6
Adafruit_NeoPixel strip1 = Adafruit_NeoPixel(2, 4, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip2 = Adafruit_NeoPixel(2, 5, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip3 = Adafruit_NeoPixel(4, 6, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip4 = Adafruit_NeoPixel(4, 7, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip5 = Adafruit_NeoPixel(3, 8, NEO_GRB + NEO_KHZ800);
 
// IMPORTANT: To reduce NeoPixel burnout risk, add 1000 uF capacitor across
// pixel power leads, add 300 - 500 Ohm resistor on first pixel's data input
// and minimize distance between Arduino and first pixel.  Avoid connecting
// on a live circuit...if you must, connect GND first.
 
void setup() {
  // This is for Trinket 5V 16MHz, you can remove these three lines if you are not using a Trinket
#if defined (__AVR_ATtiny85__)
  if (F_CPU == 16000000) clock_prescale_set(clock_div_1);
#endif
  // End of trinket special code
 
 
  strip1.begin();
  strip1.show(); // Initialize all pixels to 'off'
  strip2.begin();
  strip2.show(); // Initialize all pixels to 'off'
  strip3.begin();
  strip3.show(); // Initialize all pixels to 'off'
  strip4.begin();
  strip4.show(); // Initialize all pixels to 'off'
  strip5.begin();
  strip5.show(); // Initialize all pixels to 'off'
}
 
void loop() {
  // Some example procedures showing how to display to the pixels:
  //  colorWipe(strip1.Color(255, 0, 0), 50); // Red
  //  colorWipe(strip1.Color(0, 255, 0), 50); // Green
  strip1.setPixelColor(0, strip1.Color(138, 43, 226));
  strip1.setPixelColor(1, strip1.Color(138, 43, 226));
  strip1.setPixelColor(2, strip1.Color(138, 43, 226));
  strip1.show();
   delay(20000);
   
  strip2.setPixelColor(0, strip2.Color(138, 43, 226));
  strip2.setPixelColor(1, strip2.Color(138, 43, 226));
  strip2.setPixelColor(2, strip2.Color(138, 43, 226));
  strip3.setPixelColor(0, strip3.Color(138, 43, 226));
  strip3.setPixelColor(1, strip3.Color(138, 43, 226));
  strip3.setPixelColor(2, strip3.Color(138, 43, 226));
  strip3.setPixelColor(3, strip3.Color(138, 43, 226));
  strip3.setPixelColor(4, strip3.Color(138, 43, 226));
    strip2.show();
    strip3.show();
   delay(20000);
   
  strip4.setPixelColor(0, strip4.Color(138, 43, 226));
  strip4.setPixelColor(1, strip4.Color(138, 43, 226));
  strip4.setPixelColor(2, strip4.Color(138, 43, 226));
  strip4.setPixelColor(3, strip4.Color(138, 43, 226));
  strip4.setPixelColor(4, strip4.Color(138, 43, 226));
  strip5.setPixelColor(0, strip5.Color(138, 43, 226));
  strip5.setPixelColor(1, strip5.Color(138, 43, 226));
  strip5.setPixelColor(2, strip5.Color(138, 43, 226));
  strip5.setPixelColor(3, strip5.Color(138, 43, 226));
  strip4.show();   // Send the updated pixel colors to the hardware.
  strip5.show();
   delay(20000);
   
  strip1.setPixelColor(0, strip1.Color(0, 0, 0));
  strip1.setPixelColor(1, strip1.Color(0, 0, 0));
  strip1.setPixelColor(2, strip1.Color(0, 0, 0));
  strip1.show();
   delay(20000);
   
  strip2.setPixelColor(0, strip2.Color(0, 0, 0));
  strip2.setPixelColor(1, strip2.Color(0, 0, 0));
  strip2.setPixelColor(2, strip2.Color(0, 0, 0));
  strip3.setPixelColor(0, strip3.Color(0, 0, 0));
  strip3.setPixelColor(1, strip3.Color(0, 0, 0));
  strip3.setPixelColor(2, strip3.Color(0, 0, 0));
  strip3.setPixelColor(3, strip3.Color(0, 0, 0));
  strip3.setPixelColor(4, strip3.Color(0, 0, 0));
  strip2.show();
  strip3.show();
   delay(20000);
   
  strip4.setPixelColor(0, strip4.Color(0, 0, 0));
  strip4.setPixelColor(1, strip4.Color(0, 0, 0));
  strip4.setPixelColor(2, strip4.Color(0, 0, 0));
  strip4.setPixelColor(3, strip4.Color(0, 0, 0));
  strip4.setPixelColor(4, strip4.Color(0, 0, 0));
  strip5.setPixelColor(0, strip5.Color(0, 0, 0));
  strip5.setPixelColor(1, strip5.Color(0, 0, 0));
  strip5.setPixelColor(2, strip5.Color(0, 0, 0));
  strip5.setPixelColor(3, strip5.Color(0, 0, 0));
  strip4.show();   // Send the updated pixel colors to the hardware.
  strip5.show();
delay(20000);
 
    strip1.setPixelColor(0, strip1.Color(138, 43, 226));
  strip1.setPixelColor(1, strip1.Color(138, 43, 226));
  strip1.setPixelColor(2, strip1.Color(138, 43, 226));
  strip1.show();
   delay(20000);
   
  strip2.setPixelColor(0, strip2.Color(138, 43, 226));
  strip2.setPixelColor(1, strip2.Color(138, 43, 226));
  strip2.setPixelColor(2, strip2.Color(138, 43, 226));
  strip3.setPixelColor(0, strip3.Color(138, 43, 226));
  strip3.setPixelColor(1, strip3.Color(138, 43, 226));
  strip3.setPixelColor(2, strip3.Color(138, 43, 226));
  strip3.setPixelColor(3, strip3.Color(138, 43, 226));
  strip3.setPixelColor(4, strip3.Color(138, 43, 226)); 
  strip2.show();
  strip3.show();
   delay(20000);
   
  strip4.setPixelColor(0, strip4.Color(138, 43, 226));
  strip4.setPixelColor(1, strip4.Color(138, 43, 226));
  strip4.setPixelColor(2, strip4.Color(138, 43, 226));
  strip4.setPixelColor(3, strip4.Color(138, 43, 226));
  strip4.setPixelColor(4, strip4.Color(138, 43, 226));
  strip5.setPixelColor(0, strip5.Color(138, 43, 226));
  strip5.setPixelColor(1, strip5.Color(138, 43, 226));
  strip5.setPixelColor(2, strip5.Color(138, 43, 226));
  strip5.setPixelColor(3, strip5.Color(138, 43, 226));
  strip4.show();   // Send the updated pixel colors to the hardware.
  strip5.show();
   delay(20000);
   
    strip1.setPixelColor(0, strip1.Color(0, 0, 0));
  strip1.setPixelColor(1, strip1.Color(0, 0, 0));
  strip1.setPixelColor(2, strip1.Color(0, 0, 0));
  strip1.show();
   delay(20000);
   
  strip2.setPixelColor(0, strip2.Color(0, 0, 0));
  strip2.setPixelColor(1, strip2.Color(0, 0, 0));
  strip2.setPixelColor(2, strip2.Color(0, 0, 0));
  strip3.setPixelColor(0, strip3.Color(0, 0, 0));
  strip3.setPixelColor(1, strip3.Color(0, 0, 0));
  strip3.setPixelColor(2, strip3.Color(0, 0, 0));
  strip3.setPixelColor(3, strip3.Color(0, 0, 0));
  strip3.setPixelColor(4, strip3.Color(0, 0, 0));
  strip2.show();
  strip3.show();
   delay(20000);
   
  strip4.setPixelColor(0, strip4.Color(0, 0, 0));
  strip4.setPixelColor(1, strip4.Color(0, 0, 0));
  strip4.setPixelColor(2, strip4.Color(0, 0, 0));
  strip4.setPixelColor(3, strip4.Color(0, 0, 0));
  strip4.setPixelColor(4, strip4.Color(0, 0, 0));
  strip5.setPixelColor(0, strip5.Color(0, 0, 0));
  strip5.setPixelColor(1, strip5.Color(0, 0, 0));
  strip5.setPixelColor(2, strip5.Color(0, 0, 0));
  strip5.setPixelColor(3, strip5.Color(0, 0, 0));
  strip4.show();   // Send the updated pixel colors to the hardware.
  strip5.show();
  delay(20000);
  
Олег911
Offline
Зарегистрирован: 18.10.2020

Все равно задержка есть, не такая большая но уже 2 минуте видно разсинхрон 

sadman41
Offline
Зарегистрирован: 19.10.2016

FastLED запытайте ещё. Чисто логически - ардуины должны идти в ногу. Искать где сбивается - за просто так никто вам не будет. Это надо стенд собирать и пр. и др. Да ещё и результат непредсказуем.

Олег911
Offline
Зарегистрирован: 18.10.2020

Скажите, а может быть проблема в кварцевом резонаоре?  Может быть из за того что кварц изначально разного размера в каждой ардуине? Может не качественный где стоит? Не понимаю динамику хаотичного рассинхрона. Если был бы рассинхрон из за диодов или библиотеки то он был бы на всех одинковый скорее всего. Они бы может отставали по задумке с музыкой но работали по одной и той же схем. Может быть в платах из начально заложены погрешности, не могут они быть едентичными все. Особенно кварц я читал что в резонатор кладут камень разного размера иногда, и написано 16мгц резонатор а юыьб 15.654 и тд. Что вы думаете по этому?
Можно ли вообще кварцевый резонатор на ардуине перепаять на такую же частоту?  

sadman41
Offline
Зарегистрирован: 19.10.2016

Потенциально может быть что угодно. 

Про кварцы тут вот поясняют: http://arduino.ru/forum/pesochnitsa-razdel-dlya-novichkov/chastotomer-na-arduino-uno-i-2004-vremennyi

Но без инструментальных исследований нельзя однозначно утверждать, что дело в кварце. А если и в нём - что вы предпримете? Где найдёте более лучшие? Во что это обойдётся?

Выхода тут три:
1) Урезать осетра и более толерантно относится к рассинхрону;
2) Искать другое железо. Гарантии успеха - нет;
3) Делать workaround, разбивая весь процесс на этапы небольшой продолжительности, на которых рассинхрон не заметен. После этого с мастера давать отмашки на исполнение каждого последующего этапа.
 

P.S. MQTT - не realtime протокол. С ним даже нет гарантии синхронного старта.

Олег911
Offline
Зарегистрирован: 18.10.2020

Спасибо, лаконично и четко )

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Олег911, добавлю к вышесказанному, что  начать надо с того, что полностью переписать программу. Объявлять по 100 штук  16 битных переменных (хотя используется лишь один бит), и копировать в столбик  по 10 раз вызов одной и той же функции - никакой памяти не хватит. Конечно компилятор старается всё лишнее выкинуть, а вызовы функций оптимизировать, но его возможности не безграничны. И когда вы допишите ещё полсотни обработчиков  "ключей" наверняка начнутся проблемы.

rkit
Offline
Зарегистрирован: 23.11.2016

Никаких проблем по времени с точки зрения ардуино и кварцев быть не должно. У кварцев расхождение +-0.005%. Чтобы что-то заметное накопилось, нужны недели. Ошибки однозначно в коде/проектировании, которые, судя по всему, сделаны весьма несерьезно.

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

паузы и генерацию key надо крутить на главной ардуине

на остальных все время ждать key и по приходу начинать вывод нужных "картинок" без финальной паузы

Kakmyc
Offline
Зарегистрирован: 15.01.2018

А можно вообще все сделать на ESP и просто спамить рассылку UDP.

Олег911
Offline
Зарегистрирован: 18.10.2020

dimax пишет:

Олег911, добавлю к вышесказанному, что  начать надо с того, что полностью переписать программу. Объявлять по 100 штук  16 битных переменных (хотя используется лишь один бит), и копировать в столбик  по 10 раз вызов одной и той же функции - никакой памяти не хватит. Конечно компилятор старается всё лишнее выкинуть, а вызовы функций оптимизировать, но его возможности не безграничны. И когда вы допишите ещё полсотни обработчиков  "ключей" наверняка начнутся проблемы.

вы думаете переписать все на Fastled ? Или как можно оптимизировать код ? 
потому что я пробовал через стандартный блинк мигать с 1 ключем. Все равно идёт разсинхрон 

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Олег911, я вообще то несколько другое имел ввиду, -сам код вы начинаете писать слишком "размашисто", это чревато проблемами в перспективе. Менять библиотеки вряд ли есть смысл, они скорее всего все  блокируют прерывания(предположение).  Короче инструменты типа millis и delay будут врать что-б вы там не делали. Нужно писать свой обработчик 1-го таймера (можно через библу timerOne), который будет дёргать прерывание скажем пару раз в секунду, и вести свой счёт времени. И привязываться к нему.  Либо ещё лучше переходить на ARM, и работать через DMA, благо библиотеки под это дело тоже есть. Ну или слать с "главного" контроллера буквально каждую команду, или небольшими порциями как уже советовали выше.

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

Олег911 пишет:

вы думаете переписать все на Fastled ? Или как можно оптимизировать код ?

библиотека тут не причем - сам код написан очень плохо, куча повторов и неэффективных конструкций. Научитесь пользоваться процедурами и функциями, для похожих операций используйте массивы и циклы...

например, вместо 5 строк

  strip3.setPixelColor(0, strip3.Color(138, 43, 226));
  strip3.setPixelColor(1, strip3.Color(138, 43, 226));
  strip3.setPixelColor(2, strip3.Color(138, 43, 226));
  strip3.setPixelColor(3, strip3.Color(138, 43, 226));
  strip3.setPixelColor(4, strip3.Color(138, 43, 226));
   

можно написать одну

for(byte i =0; i<5;i++) strip3.setPixelColor(i, strip3.Color(138, 43, 226));
  

далее смотрим, что кусок

strip2.setPixelColor(0, strip2.Color(138, 43, 226));
  strip2.setPixelColor(1, strip2.Color(138, 43, 226));
  strip2.setPixelColor(2, strip2.Color(138, 43, 226));
  strip3.setPixelColor(0, strip3.Color(138, 43, 226));
  strip3.setPixelColor(1, strip3.Color(138, 43, 226));
  strip3.setPixelColor(2, strip3.Color(138, 43, 226));
  strip3.setPixelColor(3, strip3.Color(138, 43, 226));
  strip3.setPixelColor(4, strip3.Color(138, 43, 226));
    strip2.show();
    strip3.show();
 

у вас повторяется раз десять, меняется только цвет. Оформляем его как функцию, попутно заменяя одинаковые строчки на цикл. как показано выше:

  void strip23show(uint8_t r, uint8_t g, uint8_t b) {
    for(byte i =0; i<3;i++) strip2.setPixelColor(i, strip2.Color(r,g,b));
    for(byte i =0; i<5;i++) strip3.setPixelColor(i, strip2.Color(r,g,b));
    strip2.show();
    strip3.show();
 }

Теперь везде, где вы вызываете изменение цвета для лент2 3 - просто пишем

strip23show(138, 43, 226);

То же самое сделайте для лент 4 и 5 - и у вас код уменьшиться раз в десять...

 

Олег911
Offline
Зарегистрирован: 18.10.2020

dimax пишет:

Олег911, я вообще то несколько другое имел ввиду, -сам код вы начинаете писать слишком "размашисто", это чревато проблемами в перспективе. Менять библиотеки вряд ли есть смысл, они скорее всего все  блокируют прерывания(предположение).  Короче инструменты типа millis и delay будут врать что-б вы там не делали. Нужно писать свой обработчик 1-го таймера (можно через библу timerOne), который будет дёргать прерывание скажем пару раз в секунду, и вести свой счёт времени. И привязываться к нему.  Либо ещё лучше переходить на ARM, и работать через DMA, благо библиотеки под это дело тоже есть. Ну или слать с "главного" контроллера буквально каждую команду, или небольшими порциями как уже советовали выше.

А если как вы пишите на ARM перейти, повторения такого же результата на сколько вероятно? 
потому что микроконтроллеры на arm не дешево стоят. 

sadman41
Offline
Зарегистрирован: 19.10.2016

Для непрофессионала (безличностный термин) вероятность факапа всегда > 90%

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

Олег911 пишет:

А если как вы пишите на ARM перейти, повторения такого же результата на сколько вероятно? 
потому что микроконтроллеры на arm не дешево стоят. 

Олег, мне кажется, Вы не совсем верно поняли dimax... в первую дело не в контроллере... а в вашем коде

А "микроконтроллеры на arm" бывают разные, некоторые дешевле ардуинок стоят. Но, обратите внимание, совет dimax был не просто сменить контроллер, а "переходить на ARM и работать через DMA". Если вы возьмете арм и напишете примерно такой же код. как выше - он и глючить будет так же.

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

Олег911
Offline
Зарегистрирован: 18.10.2020

b707 пишет:

Олег911 пишет:

А если как вы пишите на ARM перейти, повторения такого же результата на сколько вероятно? 
потому что микроконтроллеры на arm не дешево стоят. 

Олег, мне кажется, Вы не совсем верно поняли dimax... в первую дело не в контроллере... а в вашем коде

А "микроконтроллеры на arm" бывают разные, некоторые дешевле ардуинок стоят. Но, обратите внимание, совет dimax был не просто сменить контроллер, а "переходить на ARM и работать через DMA". Если вы возьмете арм и напишете примерно такой же код. как выше - он и глючить будет так же.

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

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

Олег911
Offline
Зарегистрирован: 18.10.2020
/*
  Blink

  Turns an LED on for one second, then off for one second, repeatedly.

  Most Arduinos have an on-board LED you can control. On the UNO, MEGA and ZERO
  it is attached to digital pin 13, on MKR1000 on pin 6. LED_BUILTIN is set to
  the correct LED pin independent of which board is used.
  If you want to know what pin the on-board LED is connected to on your Arduino
  model, check the Technical Specs of your board at:
  https://www.arduino.cc/en/Main/Products

  modified 8 May 2014
  by Scott Fitzgerald
  modified 2 Sep 2016
  by Arturo Guadalupi
  modified 8 Sep 2016
  by Colby Newman

  This example code is in the public domain.

  http://www.arduino.cc/en/Tutorial/Blink
*/
#include "VirtualWire.h"
byte message[VW_MAX_MESSAGE_LEN]; // Буфер для хранения принимаемых данных
byte messageLength = VW_MAX_MESSAGE_LEN; // Размер сообщения

const int receiver_pin = 12; // Пин подключения приемника
// the setup function runs once when you press reset or power the board

void setup() {
  vw_set_rx_pin(receiver_pin); // Пин подключения приемника
  pinMode(13, OUTPUT);
  vw_setup(2000); // Скорость передачи данных (бит в секунду)
  vw_rx_start(); // Активация применика
}
void loop() {
  // Some example procedures showing how to display to the pixels:
  if (vw_get_message(message, &messageLength)) // Если есть данные..
  {
    if (message[0] == 'H')
    {
      digitalWrite(13, HIGH);
      dance();// включение по радио
    }
  }
}

int key1 = true;

void dance()
{
  //
  unsigned long myStartTime = millis();
  while (true)
  {
    unsigned long correctTime = millis();
  digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);                       // wait for a second
  digitalWrite(LED_BUILTIN, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);                       // wait for a second
 }
}

прописывал вот так код и мигал только ардуиновским диодом, все равно был разсинхрон. 
Если что я в электронике вообще первый раз занимался всю жизнь хореографией. Думаю тут код по меньше написан. По этому Думаю дело не в коде. Могу конечно ошибаться. Пока самый актуальный вариант который все говорят это сделать одну главную и с нее отдавать сигналы. Но все равно хочу покопаться с вариантом когда один старт, а потом каждая по своему коду идет. Если вы говорите что по arm скорее всего такая же будет проблема будет, если код длинный, то и пробовать не буду на ней. 

 

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

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

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

Олег911 пишет:
прописывал вот так код и мигал только ардуиновским диодом, все равно был разсинхрон.

Олег, ну какой смысл повторять одно и тоже заново? вам же уже сказали убрать библиотеку VirtualWirе -а она опять в коде

sadman41
Offline
Зарегистрирован: 19.10.2016

Заинтересовал меня этот разлёт, провёл эксперимент. Питание одинаковое - ардуины соединены по VCC/GND

Nano "Master"

Nano "Slave"

Код наколеночный (D8 - особенности конструкции самопального шилда, где D13 не выведен на гребенку):

#define MASTER
//#define BARE_METAL_CODE

#define D8_Low PORTB &= B11111110
#define D13_Low PORTB &=B11011111

#define D8_High PORTB |=B00000001
#define D13_High PORTB|=B00100000

const uint8_t slaveStartPin = 2;
const uint8_t masterStartPin = 3;

const uint8_t ledPin = 13;
const uint8_t signalPin = 8;


void setup() {
  pinMode(slaveStartPin, INPUT_PULLUP);
  pinMode(masterStartPin, OUTPUT);
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, LOW);
  pinMode(signalPin, OUTPUT);
  digitalWrite(signalPin, LOW);

#ifdef BARE_METAL_CODE
  cli();
#endif

#ifdef MASTER
  digitalWrite(masterStartPin, LOW);
#else
  while (LOW != digitalRead(slaveStartPin));
#endif

  while (true) {
    for (uint8_t i = 0; 3 > i; i++) {
#ifdef BARE_METAL_CODE
      _delay_ms(250);
      D13_High;
      D8_High;
      _delay_ms(250);
      D13_Low;
      D8_Low;
#else
      delay(250);
      digitalWrite(ledPin, HIGH);
      digitalWrite(signalPin, HIGH);
      delay(250);
      digitalWrite(ledPin, LOW);
      digitalWrite(signalPin, LOW);
#endif
    }

    for (uint8_t i = 0; 1 > i; i++) {
#ifdef BARE_METAL_CODE
      _delay_ms(1000);
      D13_High;
      D8_High;
      _delay_ms(1000);
      D13_Low;
      D8_Low;
#else
      delay(1000);
      digitalWrite(ledPin, HIGH);
      digitalWrite(signalPin, HIGH);
      delay(1000);
      digitalWrite(ledPin, LOW);
      digitalWrite(signalPin, LOW);
#endif
    }

#ifdef BARE_METAL_CODE
    _delay_ms(2000);
#else
    delay(2000);
#endif
  }
}

void loop() {}

Результат "Wiring" фрагмента: A1-A2 ~45ms, B1-B2 ~63ms

Результат "Bare metal" фрагмента: A1-A2 ~37ms, B1-B2 ~45ms

Разбег разных типов "кварцев" налицо, как грится.
sadman41
Offline
Зарегистрирован: 19.10.2016

Нашёл ещё одну Нану с "правильными" кварцами (картинка "Master" в предыдущем посте) , прогнал тест на двух одинаковых.

Результат "Wiring" фрагмента: A1-A2 ~28.2ms, B1-B2 ~28.4ms

Результат "Bare metal" фрагмента: A1-A2 ~53.7ms, B1-B2 ~53.9ms

Почему-то на "Bare metal" получился большой gap, но... суть в другом - разбег на порядки снизился.

...пока оформлял пост - ардуины с нормальными кварцами "подразбежались" и рассинхрон стал виден.

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

sadman41 пишет:

 суть в другом - разбег на порядки снизился.

Гриш, что-то я не вижу тут "на порядки" - даже в 2 раза разницы нет. Было Wiring A1-A2 = 45мс, стало 28...

Но больше интересно другое - не могу понять из твоих диаграмм - вот например разница 45мс на самой первой картинке - это за какой период. Можешь вычислить разницу частот ардуин в процентах?

sadman41
Offline
Зарегистрирован: 19.10.2016

b707 пишет:

sadman41 пишет:

 суть в другом - разбег на порядки снизился.

Гриш, что-то я не вижу тут "на порядки" - даже в 2 раза разницы нет.

В первом случае на Wiring-фрагменте gap увеличился на 18ms, во втором - на 0.2ms. Прямо на первом же цикле "моргания". 
 
Я не стремился абсолютно точно синхронизироваться, я оценивал разбег фронтов через определенный промежуток времени.
 

b707 пишет:
Но больше интересно другое - не могу понять из твоих диаграмм - вот например разница 45мс на самой первой картинке - это за какой период. Можешь вычислить разницу частот ардуин в процентах?

Там, в верхней линейке секунды отмечены - +1s, +2s...
 
Разницу частот... Где-то, вроде, упоминался скетчик, который реальную частоту вычисляет. Dimax подскажет если - я промеряю.
 
b707
Offline
Зарегистрирован: 26.05.2017

sadman41 пишет:

В первом случае на Wiring-фрагменте gap увеличился на 18ms, во втором - на 0.2ms. Прямо на первом же цикле "моргания".
Аааа это я не понял куда смотреть
 
Я думал, что эти цифры - уже разница, а их оказывается между собой сравнивать надо...
sadman41
Offline
Зарегистрирован: 19.10.2016

Ну да, поленился описать ход эксперимента, поэтому не очень понятно.

Две ардуины - мастер и слейв. Мастер пинает слейва и они начинают промигивать по одному и тому же сценарию.

Для локализации проблемного места измерялось время отставания момента зажигания светодиода на слейве от зажигания светодиода на мастере. И оно нарастало - за 6 секунд на 18мс... В целом, при простом алгоритме, Wiring радикально картину не портит, проблема в кварцевом резонаторе. Delay на millis() от delay на ассемблеровских фрагментах сильно тут не отличается.

А вот далее начинаются наслоения - VirtualWire на таймере и пр, что усугубляет проблему.

Но, думаю, при аккуратной работе с библиотеками и перестройке командного аппарата, можно добиться удовлетворительного результата.

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

Если задержки делать на millis(), то никаие  VirtualWire не должны мешать. Чтобы сбить millis необхомо запретить прерывания на 2мс или больше. Я код VirtualWire не смотрел, но вряд ли там такая шняга.

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

sadman41 пишет:

Разницу частот... Где-то, вроде, упоминался скетчик, который реальную частоту вычисляет. Dimax подскажет если - я промеряю.

Удобнее наверно тем-же лог. анализатором и измерить частоту с нанок, а сигнал с таймера взять. Вот пример, при ocr2a=0 на выходе будет  8МГц.
pinMode(11,OUTPUT);
TCCR2A=(1<<COM2A0)|(1<<WGM21); //mode 2 CTC
TCCR2B=1<<CS20;
OCR2A=0;

 

 

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Вот по этому я и писал, что все задержки должны отслеживаться только на мастере и он должен высылать "номер картинки". Слейвы в основном слушают мастера и выводят картинки в зависимости от полученного номера.