ARDUINO Переключение светодиодов кнопкой

michell

✩✩✩✩✩✩✩
7 Окт 2020
6
0
37
кстово
Приветствую!!! Вопрос такого плана \это схема.
1602092069384.png


ткните что не так делаю

#define DATA_PIN 13
#define LATCH_PIN 12
#define CLOCK_PIN 11
#define BUTTON_PIN 10

int clicks = 0;
boolean buttonWasUp = true;
byte led[8] = {
0b01111111, 0b10111111, 0b11011111, 0b11101111, 0b11111011,
0b11111011, 0b11111101, 0b11111110,
};
byte led0[8] = {

};

void setup()
{
pinMode(DATA_PIN, OUTPUT);
pinMode(CLOCK_PIN, OUTPUT);
pinMode(LATCH_PIN, OUTPUT);
pinMode(BUTTON_PIN, INPUT_PULLUP);
}

void loop()
{
if (buttonWasUp && !digitalRead(BUTTON_PIN)) {
delay(10);
if (!digitalRead(BUTTON_PIN))
clicks = (clicks + 1) % 16;
}
buttonWasUp = digitalRead(BUTTON_PIN);
digitalWrite(LATCH_PIN, LOW);
shiftOut(DATA_PIN, CLOCK_PIN, LSBFIRST, led[clicks]);
shiftOut(DATA_PIN, CLOCK_PIN, LSBFIRST, led0[clicks]);
digitalWrite(LATCH_PIN, HIGH);
}

пасути хотелось бы что бы загорался один led при нажатии по порядку
\
 

bort707

★★★★★★✩
21 Сен 2020
3,062
912
Вы этот вопрос уже на третьем форуме размещаете, вместо того чтоб самому чуть подумать.

ткните что не так делаю
Что не так делаете? - берете чужой скетч от 8 диодов, а пихаете в него 16. У вас переменная clicks принимает значения от 0 до 15, а элементов в массиве leds[] - всего восемь. В итоге распахиваете память.
Ну и еще кучу всего надо поправить, что простой заменой 8 на 16 не сработает.
 

michell

✩✩✩✩✩✩✩
7 Окт 2020
6
0
37
кстово
исправил!!!

#define DATA_PIN 13
#define LATCH_PIN 12
#define CLOCK_PIN 11
#define BUTTON_PIN 10

int clicks = 0;
boolean buttonWasUp = true;
byte led[16] = {
0b01111111, 0b10111111, 0b11011111, 0b11101111, 0b11110111,
0b11111011, 0b11111101, 0b11111110,
};
byte led0[8] = {

};

void setup()
{
pinMode(DATA_PIN, OUTPUT);
pinMode(CLOCK_PIN, OUTPUT);
pinMode(LATCH_PIN, OUTPUT);
pinMode(BUTTON_PIN, INPUT_PULLUP);
}

void loop()
{
if (buttonWasUp && !digitalRead(BUTTON_PIN)) {
delay(10);
if (!digitalRead(BUTTON_PIN))
clicks = (clicks + 1) % 16;
}
buttonWasUp = digitalRead(BUTTON_PIN);
digitalWrite(LATCH_PIN, LOW);
shiftOut(DATA_PIN, CLOCK_PIN, LSBFIRST, led[clicks]);
shiftOut(DATA_PIN, CLOCK_PIN, LSBFIRST, led0[clicks]);
digitalWrite(LATCH_PIN, HIGH);
}

Только непонятки с led. на одном регистре они загораются и 1 тухнет по порядку а на другом регистре все как надо

извините я не шарю в с++.дооооо меня доходит быстрей методом проб и ошибок.
 

bort707

★★★★★★✩
21 Сен 2020
3,062
912
что ты исправил? размер массива led[] поставил 16? - думаешь этого достаточно?
У тебя еще есть массив led0[] - он тоже неверного размера.
Ну и главное - мало поменять размер массивов, их еще нужно правильно заполнить.
извините я не шарю в с++.
прости, тогда не ясно, какой помощи ты просишь? - имхо, если сам не шаришь - иди заказывай в коммерческом разделе
 

michell

✩✩✩✩✩✩✩
7 Окт 2020
6
0
37
кстово
Ребята спасибо всем огромное форум пушка вот скетч кому интересно опробуйте


#include <SPI.h>
bool _gtv1;
bool _gen1I = 0;
bool _gen1O = 0;
unsigned long _gen1P = 0UL;
byte _74HC5952OB1 = 0;
byte _74HC5952OB2 = 0;
byte _74HC5952TB = 0;
bool _74HC5952NS = 0;
byte _74HC5951OB1 = 0;
byte _74HC5951OB2 = 0;
byte _74HC5951TB = 0;
bool _74HC5951NS = 0;
bool _count1I = 0;
int _count1_Value = 0;
bool _count1MaxLO = 0;
bool _bounseInputD2S = 0;
bool _bounseInputD2O = 0;
unsigned long _bounseInputD2P = 0UL;

void setup()
{
pinMode(2, INPUT_PULLUP);


_bounseInputD2O = digitalRead(2);
SPI.begin();
pinMode(10, OUTPUT);
pinMode(8, OUTPUT);
pinMode(8, OUTPUT);

}
void loop()
{


bool _bounceInputTmpD2 = (digitalRead (2));

if (_bounseInputD2S)
{
if (millis() >= (_bounseInputD2P + 40))
{_bounseInputD2O= _bounceInputTmpD2; _bounseInputD2S=0;}
}
else
{
if (_bounceInputTmpD2 != _bounseInputD2O )
{_bounseInputD2S=1; _bounseInputD2P = millis();}
}




//Плата:1
_74HC5952NS = 0;
bitWrite(_74HC5952TB, 0, 0);
bitWrite(_74HC5952TB, 1, 0);
bitWrite(_74HC5952TB, 2, 0);
bitWrite(_74HC5952TB, 3, 0);
bitWrite(_74HC5952TB, 4, 0);
bitWrite(_74HC5952TB, 5, 0);
bitWrite(_74HC5952TB, 6, 0);
bitWrite(_74HC5952TB, 7, 0);
if(! (_74HC5952TB == _74HC5952OB1)){_74HC5952OB1 = _74HC5952TB; _74HC5952NS = 1;}
bitWrite(_74HC5952TB, 0, 0);
bitWrite(_74HC5952TB, 1, 0);
bitWrite(_74HC5952TB, 2, 0);
bitWrite(_74HC5952TB, 3, 0);
bitWrite(_74HC5952TB, 4, 0);
bitWrite(_74HC5952TB, 5, 0);
bitWrite(_74HC5952TB, 6, 0);
bitWrite(_74HC5952TB, 7, 0);
if(! (_74HC5952TB == _74HC5952OB2)){_74HC5952OB2 = _74HC5952TB; _74HC5952NS = 1;}
if (_74HC5952NS) {
digitalWrite(8, 0);
SPI.transfer(_74HC5952OB2);
SPI.transfer(_74HC5952OB1);
digitalWrite(8, 1);}
if (!(_bounseInputD2O)) {if (! _gen1I) { _gen1I = 1; _gen1O = 1; _gen1P = millis(); } } else { _gen1I = 0 ; _gen1O= 0; } if (_gen1I ) { if (_gen1O) { if ( _isTimer( _gen1P , 50 )) { _gen1P = millis(); _gen1O = 0; } } else { if ( _isTimer( _gen1P , 50 )) { _gen1P = millis(); _gen1O = 1; } } }
if (_gtv1){_count1_Value = 0;} else {
if (_gen1O){
if ( ! _count1I) {
_count1I = 1;
_count1_Value = _count1_Value + 1;
}} else {
_count1I = 0;}
}
_count1MaxLO = _count1_Value >= 16;
_74HC5951NS = 0;
bitWrite(_74HC5951TB, 0, (_count1_Value == 1));
bitWrite(_74HC5951TB, 1, (_count1_Value == 2));
bitWrite(_74HC5951TB, 2, (_count1_Value == 3));
bitWrite(_74HC5951TB, 3, (_count1_Value == 4));
bitWrite(_74HC5951TB, 4, (_count1_Value == 5));
bitWrite(_74HC5951TB, 5, (_count1_Value == 6));
bitWrite(_74HC5951TB, 6, (_count1_Value == 7));
bitWrite(_74HC5951TB, 7, (_count1_Value == 8));
if(! (_74HC5951TB == _74HC5951OB1)){_74HC5951OB1 = _74HC5951TB; _74HC5951NS = 1;}
bitWrite(_74HC5951TB, 0, (_count1_Value == 9));
bitWrite(_74HC5951TB, 1, (_count1_Value == 10));
bitWrite(_74HC5951TB, 2, (_count1_Value == 11));
bitWrite(_74HC5951TB, 3, (_count1_Value == 12));
bitWrite(_74HC5951TB, 4, (_count1_Value == 13));
bitWrite(_74HC5951TB, 5, (_count1_Value == 14));
bitWrite(_74HC5951TB, 6, (_count1_Value == 15));
bitWrite(_74HC5951TB, 7, (_count1_Value == 16));
if(! (_74HC5951TB == _74HC5951OB2)){_74HC5951OB2 = _74HC5951TB; _74HC5951NS = 1;}
if (_74HC5951NS) {
digitalWrite(8, 0);
SPI.transfer(_74HC5951OB2);
SPI.transfer(_74HC5951OB1);
digitalWrite(8, 1);}
_gtv1 = _count1MaxLO;






}

bool _isTimer(unsigned long startTime, unsigned long period )
{
unsigned long currentTime;
currentTime = millis();
if (currentTime>= startTime) {return (currentTime>=(startTime + period));} else {return (currentTime >=(4294967295-startTime+period));}
}
 

bort707

★★★★★★✩
21 Сен 2020
3,062
912
@michell, жуть какая-то. Код должен был получится не длиннее первого, того что на 8 диодов.
И научитесь вставлять код правильно, как вас только модераторы терпят :)
 

DAK

★★★✩✩✩✩
8 Окт 2020
517
137
Я просто не могу понять конечной цели. Если цель в том, чтобы использовать микроконтроллер именно в таком режиме, и других целей не ставится, и Вам главное именно здесь и сейчас сделать именно то, что Вы сделали, и более никогда не вернётесь к это теме, то пусть будет так. Если же Вы планируете далее работать с микроконтроллерами, то тогрда я позволю себе немного написать в этой теме...
Думаю что для программирования контроллера не надо шарить в с++, надо просто понимать сам принцип программирования, во всех языках есть циклы, условия, массивы, я даже не буду говорить про функции, классы, структуры и прочее. Да, сам для себя не так давно открыл то, что в с++ есть много тонкостей и нюансов, и для познания всех тонкостей надо пройти нелёгкий путь. Если Вы собираетесь идти дальше, то лучше б и правда почитать хотя б учебник по информатике. По идее вся задача сводится к такому виду: зафиксировано событие клика по кнопке (то бишь сперва её нажали, потом ей отпустили), после этого события надо вызвать функцию, которая сперва высчитает какой сейчас светодиод включен, потом включит следующий и включит предыдущий. я даже не знаю зачем тут millis(). Я понимаю, что пофиг на форматирование, но это как неотъемлемая часть, даже просто (хотя бы) щёлкнуть Ctrl+T и может стоит поболее поставить комментариев. Ведь Вы с какой то целью выкладываете код, комментарии помогут остальным хотя бы понять ход Ваших мыслей, и в принципе многие даже укажут на ошибки, либо натолкнут Вас на правильный подход. Я тут сам недавно, и не без трений с участниками, но всё же могу точно сказать, что мне тут помогли, и я стараюсь прислушиваться и совершенствовать свой код. Ниже я в Ваш же код просто вставил несколько циклов, думаю он тоже будет работать. Я пытался понять ход Ваших мыслей и Ваш алгоритм, но увы у меня ничего не получилось
C++:
#include <SPI.h>
bool _gtv1;
bool _gen1I = 0;
bool _gen1O = 0;
unsigned long _gen1P = 0UL;
byte _74HC5952OB1 = 0;
byte _74HC5952OB2 = 0;
byte _74HC5952TB = 0;
bool _74HC5952NS = 0;
byte _74HC5951OB1 = 0;
byte _74HC5951OB2 = 0;
byte _74HC5951TB = 0;
bool _74HC5951NS = 0;
bool _count1I = 0;
int _count1_Value = 0;
bool _count1MaxLO = 0;
bool _bounseInputD2S = 0;
bool _bounseInputD2O = 0;
unsigned long _bounseInputD2P = 0UL;

void setup()
{
  pinMode(2, INPUT_PULLUP);
  _bounseInputD2O = digitalRead(2);
  SPI.begin();
  pinMode(10, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(8, OUTPUT);

}
void loop()
{


  bool _bounceInputTmpD2 = (digitalRead (2));

  if (_bounseInputD2S)
  {
    if (millis() >= (_bounseInputD2P + 40))
    {
      _bounseInputD2O = _bounceInputTmpD2;
      _bounseInputD2S = 0;
    }
  }
  else
  {
    if (_bounceInputTmpD2 != _bounseInputD2O )
    {
      _bounseInputD2S = 1;
      _bounseInputD2P = millis();
    }
  }
  //Плата:1
  _74HC5952NS = 0;
  for (byte i = 0; i < 8; i++) {
    bitWrite(_74HC5952TB, i, 0);
  }
  if (! (_74HC5952TB == _74HC5952OB1)) {
    _74HC5952OB1 = _74HC5952TB;
    _74HC5952NS = 1;
  }
  for (byte i = 0; i < 8; i++) {
    bitWrite(_74HC5952TB, i, 0);
  }
  if (! (_74HC5952TB == _74HC5952OB2)) {
    _74HC5952OB2 = _74HC5952TB;
    _74HC5952NS = 1;
  }
  if (_74HC5952NS) {
    digitalWrite(8, 0);
    SPI.transfer(_74HC5952OB2);
    SPI.transfer(_74HC5952OB1);
    digitalWrite(8, 1);
  }
  if (!(_bounseInputD2O)) {
    if (! _gen1I) {
      _gen1I = 1;
      _gen1O = 1;
      _gen1P = millis();
    }
  } else {
    _gen1I = 0 ;
    _gen1O = 0;
  } if (_gen1I ) {
    if (_gen1O) {
      if ( _isTimer( _gen1P , 50 )) {
        _gen1P = millis();
        _gen1O = 0;
      }
    } else {
      if ( _isTimer( _gen1P , 50 )) {
        _gen1P = millis();
        _gen1O = 1;
      }
    }
  }
  if (_gtv1) {
    _count1_Value = 0;
  } else {
    if (_gen1O) {
      if ( ! _count1I) {
        _count1I = 1;
        _count1_Value = _count1_Value + 1;
      }
    } else {
      _count1I = 0;
    }
  }
  _count1MaxLO = _count1_Value >= 16;
  _74HC5951NS = 0;
  for (byte i = 0; i < 8; i++) {
    bitWrite(_74HC5951TB, i, (_count1_Value == (i + 1)));
  }
  if (! (_74HC5951TB == _74HC5951OB1)) {
    _74HC5951OB1 = _74HC5951TB;
    _74HC5951NS = 1;
  }
  for (byte i = 0; i < 8; i++) {
    bitWrite(_74HC5951TB, i, (_count1_Value == (i + 8)));
  }
  if (! (_74HC5951TB == _74HC5951OB2)) {
    _74HC5951OB2 = _74HC5951TB;
    _74HC5951NS = 1;
  }
  if (_74HC5951NS) {
    digitalWrite(8, 0);
    SPI.transfer(_74HC5951OB2);
    SPI.transfer(_74HC5951OB1);
    digitalWrite(8, 1);
  }
  _gtv1 = _count1MaxLO;
}

bool _isTimer(unsigned long startTime, unsigned long period )
{
  unsigned long currentTime;
  currentTime = millis();
  if (currentTime >= startTime) {
    return (currentTime >= (startTime + period));
  } else {
    return (currentTime >= (4294967295 - startTime + period));
  }
}
 

Эдуард Анисимов

★★★★★★✩
23 Сен 2019
2,407
976
58
Марий-Эл
пасути хотелось бы что бы загорался один led при нажатии по порядку
Давайте определимся.
То что Вы написали - огромный, бесполезный огород.

Вопрос такой, Вы сами хотите опрашивать кнопку или можете воспользоваться готовой библиотекой?

Я правильно понял? Алгоритм такой - Подаём питание, ничего не происходит.
Нажимаем кнопку, загорается первый светодиод.
Снова нажимаем предыдущий гаснет, загорается следующий и так по порядку.
Верно описал? Или как то по другому?
 

Эдуард Анисимов

★★★★★★✩
23 Сен 2019
2,407
976
58
Марий-Эл
Дополнительно вопрос.
Вам нужно знать какой светодиод горит в данный момент или достаточно просто одиночный прогнать и всё?
 

Эдуард Анисимов

★★★★★★✩
23 Сен 2019
2,407
976
58
Марий-Эл
У меня подозрение, что пост писался для вставки ссылки на другой сервер.

Но решение я всё таки выложу.
Сразу предупреждаю, код писался в лоб.
Используются глобальные переменные и другие мелочи.
И решение имеет 100500 решений. Два я выложу а пять штук буду в голове держать.

Решение без отслеживания какой горит. Отслеживание косвенное:
#include "Arduino.h"
#include "GyverButton.h"


#define PIN_DATA  8                                                        // Вход данных
#define PIN_CLK   10                                                       // Тактирование сдвига
#define PIN_LCK   9                                                        // Защёлкивание данных в выходном регистре
#define PIN_KEY   7                                                        // Кнопка

uint8_t Counter_Shift;

GButton Key(PIN_KEY, LOW_PULL, NORM_OPEN);

void setup()
{
  pinMode(PIN_DATA, OUTPUT);
  pinMode(PIN_CLK, OUTPUT);
  pinMode(PIN_LCK, OUTPUT);
  digitalWrite(PIN_DATA, LOW);
  digitalWrite(PIN_CLK, LOW);
  digitalWrite(PIN_LCK, LOW);
  Counter_Shift = 16;
}

void loop()
{
  Key.tick();                                                             // обязательная функция отработки. Должна постоянно опрашиваться
  if(Key.isSingle())                                                      // Если кнопка коротко нажата, заходим в условие
  {
    if(Counter_Shift == 16)                                               // Если счётчик сдвигов равен 16, значит это первое нажатие кнопки
    {
      digitalWrite(PIN_DATA, HIGH);                                       // Выставляем "1" на входе данных сдвигового регистра
      digitalWrite(PIN_CLK, HIGH);                                        // Сдвигаем данные, единица запишется в первую ячейку сдвигового регистра
      digitalWrite(PIN_LCK, HIGH);                                        // Защёлкиваем данные сдвигового регистра в выходном каскаде
      digitalWrite(PIN_CLK, LOW);                                         // Сбрасываем все установленные сигналы в "0"
      digitalWrite(PIN_LCK, LOW);                                         //
      digitalWrite(PIN_DATA, LOW);                                        //
      Counter_Shift--;                                                    // Вычитаем "1" из счётчика сдвигов
    }
    else if(Counter_Shift != 0)                                           // Если счётчик сдвигов не равен "0"
    {
      digitalWrite(PIN_CLK, HIGH);                                        // Сдвигаем единицу в сдвиговом регистре на одну позицию, загорится следующий светодиод
      digitalWrite(PIN_LCK, HIGH);
      digitalWrite(PIN_CLK, LOW);
      digitalWrite(PIN_LCK, LOW);
      Counter_Shift--;
    }
    else                                                                  // Если счётчик сдвигов обнулился, инициализируем его заново и всё начнётся с начала
    {
      Counter_Shift = 16;
    }
  }
}
Решение с возможность отслеживания:
#include "Arduino.h"
#include "GyverButton.h"


#define PIN_DATA  8                                                       // Вход данных
#define PIN_CLK   10                                                      // Тактирование сдвига
#define PIN_LCK   9                                                       // Защёлкивание данных в выходном регистре
#define PIN_KEY   7                                                       // Кнопка

uint8_t   Counter_Shift;                                                  // Счётчик сдвигов
uint16_t  Data_Shift;                                                     // Переменная в которой мы будем осуществлять сдвиг

GButton Key(PIN_KEY, LOW_PULL, NORM_OPEN);

void Transmit595(void);

void setup()
{
  pinMode(PIN_DATA, OUTPUT);
  pinMode(PIN_CLK, OUTPUT);
  pinMode(PIN_LCK, OUTPUT);
  digitalWrite(PIN_DATA, LOW);
  digitalWrite(PIN_CLK, LOW);
  digitalWrite(PIN_LCK, LOW);
  Counter_Shift = 16;
  Data_Shift = 0b0000000000000001;                                        // Переменная инициализируется бинарным числом для наглядности
}

void loop()
{
  // Здесь можно производить какую либо обработку переменной Data_Shift содержащую текущую информацию о включенном светодиоде
  // Но по быстрому
  // Иначе собьётся функция чтения кнопки. Что бы не сбивалось, лучше кнопку сделать с прерыванием


  Key.tick();                                                             // обязательная функция отработки. Должна постоянно опрашиваться
  if(Key.isSingle())                                                      // Если кнопка коротко нажата, заходим в условие
  {
    if(Counter_Shift != 0)                                                // Счётчик не равен 0
    {
      Transmit595();                                                      // С помощью функции передаём значение переменной Data_Shift в регистр сдвига
      Data_Shift = Data_Shift << 1;                                       // Сдигаем влево, чтобы загорелся следующий светодиод а предыдущий потух
      Counter_Shift--;                                                    // Вычитаем 1 из счётчика сдвигов
    }
    else Counter_Shift = 16;
  }
}

void Transmit595(void)
{
  uint16_t Temp = Data_Shift;                                           // Запоминаем во временной переменной значение выводимое в сдвиговый регистр
  uint8_t  Count = 16;                                                  // Счётчик переданных бит

  while(Count != 0)
  {
    digitalWrite(PIN_DATA, (Temp & 0x0001));                            // С помощью маски отсекаем все ненужные биты, оставшийся последним бит пихаем в сдвиговый реистр
    digitalWrite(PIN_CLK, HIGH);                                        // Сдвигаем данные, бит запишется в первую ячейку сдвигового регистра
    digitalWrite(PIN_LCK, HIGH);                                        // Защёлкиваем данные сдвигового регистра в выходном каскаде
    digitalWrite(PIN_CLK, LOW);                                         // Сбрасываем все установленные сигналы в "0"
    digitalWrite(PIN_LCK, LOW);                                         //
    Temp = Temp >> 1;                                                   // Сдвигаем выводимомое значение на 1 бит вправо
    Count--;                                                            // Вычитаем 1 из счётчмка переданных бит
  }
}
Код не проверял, могут быть мелкие ошибки.
 
Изменено: