Помогите новичку с программой

vasjn23
Offline
Зарегистрирован: 14.05.2013

Здравствуйте. Взялся за изучение Arduino. Но немного застрял.  Подключил к плате сдвиговый регистр 595.

Получается следуюющая картина. Светодиодики, подключенные к выходу 595-го зажигаються в одну сторону и гаснут. А я хочу, чтобы они начала зажглись по одному, а потом по одному погасли ( туда и обратно). И так в цикле.

Но у меня прога встала..


int latchPin = 5;
int clockPin = 6;
int dataPin = 4;
 
byte leds = 0;
 
void setup() 
{
  pinMode(latchPin, OUTPUT);
  pinMode(dataPin, OUTPUT);  
  pinMode(clockPin, OUTPUT);
}
 
void loop() 
{
  leds = 0;
  updateShiftRegister();
  delay(500);
  for (int i = 8; i >= 0; i--)
  {
    bitSet(leds, i);
    updateShiftRegister();
    delay(500);
  }
  for (int i=0; i < 8; i++)
  {
    bitClear(leds, i);
    updateShiftRegister();
    delay(500);
  }
}
void updateShiftRegister()
{
   digitalWrite(latchPin, LOW);
   shiftOut(dataPin, clockPin, LSBFIRST, leds);
   digitalWrite(latchPin, HIGH);
}

Подскажите - где засела ошибка???

Если убрать второй for - то все работает - понимаю что где-то конфликт, а где ???

vasjn23
Offline
Зарегистрирован: 14.05.2013
 for (int i = 8; i >= 0; i--)

убрал знак "=" из равенства (больше или равно - заработало). Только теперь не функционирует одни светодиод - с выхода Q7. Почему так?

leshak
Offline
Зарегистрирован: 29.09.2011

Скорее всего не это причина ваших проблем, но тоже косяк:

строка 19-ть. Вы начинаете с i=8, заканчиваете на i=0. Всего - пытаетесь установить 9-ть битов :) А их 8-мь. Биты у нас нумеруются с 0-левого, по 7-дьмой (во втором цикле - вы верно по ним проходите).

Начинать нужно с i=7

И еще. Везде вместо int, правильней было-бы использовать byte

UPD. Убирать знак равенства не нужно было. В таком варианте вы нулевой бит не выставляете. Возможно поэтому и не горит что-то.

vasjn23
Offline
Зарегистрирован: 14.05.2013

Проблему этим не решить - поскольку не светиться "0" светодиод, а с 7-м то все впрорядке.

Почему byte корректнее?

leshak
Offline
Зарегистрирован: 29.09.2011

vasjn23 пишет:

Проблему этим не решить - поскольку не светиться "0" светодиод, а с 7-м то все впрорядке.

Угу. А с 8-мым как дело обстоит?

Читайте апдейт. Пока на набирал, вы внесли поправку - убрали знак равно. ВОт вам нулевой и не светится. Так как цикл выполняется только когда i>0, а ноль не больше нуля.

vasjn23 пишет:

Почему byte корректнее?

Потому, что i - у вас не бывает больше 256, не бывает отрицательным.

То же самое - номера пинов. Ни большими, ни отрицательными - не бывают. Следовательно - лишний расход памяти.

То же самое и Led-дом. Если у вас всего 8-мь светиков, то byte будет самым "минимально достаточным" типом.

Вообщем лучше сразу привыкать осознанно выбирать наиболее подходящий тип. А в некоторых случаях - ошибка с типами будет истичником трудно-уловимых проблем.

vasjn23
Offline
Зарегистрирован: 14.05.2013

leshak пишет:

UPD. Убирать знак равенства не нужно было. В таком варианте вы нулевой бит не выставляете. Возможно поэтому и не горит что-то.

 

Да НО со знаком равенства получаем затык после первого for и цикл останавливается. Программа не идет дольше.

leshak
Offline
Зарегистрирован: 29.09.2011
for (byte i = 7; i >= 0; i--)

 

vasjn23
Offline
Зарегистрирован: 14.05.2013

Спосибо - соориентировался. Сделал так

int latchPin = 5;
int clockPin = 6;
int dataPin = 4;
 
byte leds = 0;
 
void setup() 
{
  pinMode(latchPin, OUTPUT);
  pinMode(dataPin, OUTPUT);  
  pinMode(clockPin, OUTPUT);
}
 
void loop() 
{
  leds = 0;
  updateShiftRegister();
  delay(5000);
  for (int i = 7; i >-1; i--)
  {
    bitSet(leds, i);
    updateShiftRegister();
    delay(500);
  }
  delay(500);
  for (byte i=7; i > 0; i--)
  {
    bitClear(leds, i);
    updateShiftRegister();
    delay(500);
  }
}
void updateShiftRegister()
{
   digitalWrite(latchPin, LOW);
   shiftOut(dataPin, clockPin, LSBFIRST, leds);
   digitalWrite(latchPin, HIGH);
}

Процесс пошел. Спасибо за терпение. Вопрос пока снят ( до дальнейшей модернизации ).

leshak
Offline
Зарегистрирован: 29.09.2011

 

leshak пишет:

UPD. Убирать знак равенства не нужно было. В таком варианте вы нулевой бит не выставляете. Возможно поэтому и не горит что-то.

 

Да НО со знаком равенства получаем затык после первого for и цикл останавливается. Программа не идет дольше.

[/quote]

Ну, ok. Не хотите равенства - не нужно ;)

Делайте свой for(byte i=8;i>0...

Но тогда, вам нужно будет делать  bitSet(leds, i-1);

Тогда i у вас будет пробегать 8..1, а в bitSet уходить 7..0

leshak
Offline
Зарегистрирован: 29.09.2011

И да, кажись прогнал я (хотя вы, похоже заметили эту мою ошибку). В первом цикле, i таки бывает отрицательным. Значит нужен знаковый тип. byte - не подходит. Нужен либо char  (может принимать -128..127), либо int (один байт памяти будем расходовть зря).

И да :)

i >-1

это тоже самое что 

i>=0

:) Это вы верно заметили. Но, imho, i>=0 - все таки луче читается.

vasjn23
Offline
Зарегистрирован: 14.05.2013

На самом деле про byte/int - я только благодаря вам заметил. А то что читаемость i>=0 лучше - это бесспорно. Хотя именно в таком ключе программа и не запускалась...

 

vasjn23
Offline
Зарегистрирован: 14.05.2013

А вот теперь назрел вопрос - а как прикрутить 2-й сдвиговый регистр с теми-же функциями. Но теперь там количество выводов 16 получается.

 

leshak
Offline
Зарегистрирован: 29.09.2011

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

vasjn23
Offline
Зарегистрирован: 14.05.2013

спасибо. Пошел искать.

vasjn23
Offline
Зарегистрирован: 14.05.2013

Опять у  меня какой-то непонятный момент...

/Пин подключен к ST_CP входу 74HC595
const int latchPin = 5;
//Пин подключен к SH_CP входу 74HC595
const int clockPin = 6;
//Пин подключен к DS входу 74HC595
const int dataPin = 4;
 
void setup() {
   //устанавливаем режим OUTPUT
  pinMode(latchPin, OUTPUT);
  pinMode(dataPin, OUTPUT); 
  pinMode(clockPin, OUTPUT);
}
 
void loop() {
  // проходим циклом по всем 16 выходам двух регистров
  for (int thisLed = 0; thisLed < 16; thisLed++) {
    // записываем сигнал в регистр для очередного светодиода
    registerWrite(thisLed, HIGH);
    // если это не первый светодиод, то отключаем предыдущий
    if (thisLed > 0) {
      registerWrite(thisLed-1, LOW);
    }
    // если это первый светодиод, то отключаем последний
    else {
      registerWrite(15, LOW);
    }

          // делаем паузу перед следующией итерацией
    delay(500);
  }
 
}
 
// этот метод отсылает бит на сдвиговый регистр
 
void registerWrite(int whichPin, int whichState) {
  // для хранения 16 битов используем unsigned int
  unsigned int bitsToSend = 0;   
 
  // выключаем светодиоды на время передачи битов
  digitalWrite(latchPin, LOW);
 
  // устанавливаем HIGH в соответствующий бит
  bitWrite(bitsToSend, whichPin, whichState);
 
  // разбиваем наши 16 бит на два байта
  // для записи в первый и второй регистр
  byte registerTwo = highByte(bitsToSend);
  byte registerOne = lowByte(bitsToSend);
 
  // "проталкиваем" байты в регистры
  shiftOut(dataPin, clockPin, MSBFIRST, registerTwo);
  shiftOut(dataPin, clockPin, MSBFIRST, registerOne);
 
  // "защелкиваем" регистр, чтобы биты появились на выходах регистра
  digitalWrite(latchPin, HIGH);
}

Код из примера работы со сдвиговым регисторм. НО есть нюанс. У меня  задача та-же что  в прошлый раз - постепенное поднимание лесенки (без гашения) и постепенное погасание светодиода. В тексте есть функция (строка 21) которая определяет кокой светодиод горит, и гасит предыдущий. Если её убрать - то ничего не меняется, почему?? Более того, программа запускается , а с опросником for - нет.

vasjn23
Offline
Зарегистрирован: 14.05.2013

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

int latchPin = 5;
int clockPin = 6;
int dataPin = 4;
 
char leds = 0;
 
void setup() 
{
  pinMode(latchPin, OUTPUT);
  pinMode(dataPin, OUTPUT);  
  pinMode(clockPin, OUTPUT);
}
 
void loop() 
{
  leds = 0;
    delay(500);
  for (int i = 15; i >-1; i--)
  {
    registerWrite(i, HIGH);
    delay(500);
  }
  delay(500);
  for (int i=15; i >= 0; i--)
  {
    registerWrite(i, HIGH);
    delay(500);
  }
}
void registerWrite(int whichPin, int whichState) {
  // для хранения 16 битов используем unsigned int
  unsigned int bitsToSend = 0;   
 
  // выключаем светодиоды на время передачи битов
  digitalWrite(latchPin, LOW);
 
  // устанавливаем HIGH в соответствующий бит
  bitWrite(bitsToSend, whichPin, whichState);
 
  // разбиваем наши 16 бит на два байта
  // для записи в первый и второй регистр
  byte registerTwo = highByte(bitsToSend);
  byte registerOne = lowByte(bitsToSend);
 
  // "проталкиваем" байты в регистры
  shiftOut(dataPin, clockPin, MSBFIRST, registerTwo);
  shiftOut(dataPin, clockPin, MSBFIRST, registerOne);
 
  // "защелкиваем" регистр, чтобы биты появились на выходах регистра
  digitalWrite(latchPin, HIGH);
}

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

leshak
Offline
Зарегистрирован: 29.09.2011

> Если её убрать - то ничего не меняется, почему

Тут зависит от того что вы вы ожидали. Внутри функции registerWrite у вас все равно выключаются все, кроме того которому вы ставите HIGH. 

А когда вы вызвыете  registerWrite(ПОФИГ, LOW); - вы все равно гасите ВСЕ диоды.

Что вы, в конечном итоге отправляете на сдвиговый? bitsToSend . А какое у него значение? Вначале - ноль. Потом, возможно, выставим ему какой-то бит, и тогда отправим. 

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

Самое простое - добивать слово static перед unsigned int

Либо вынести объявление unsigned int bitsToSend = 0;  из функции (объявить его в начале скетча) - сделать глобальной переменной.

>Более того, программа запускается , а с опросником for - нет.

А тут я вообще не понял про что вы.

 

leshak
Offline
Зарегистрирован: 29.09.2011

Вообщем попробуйте

void registerWrite(int whichPin, int whichState) {
  // для хранения 16 битов используем unsigned int
  static unsigned int bitsToSend = 0;  

 

vasjn23
Offline
Зарегистрирован: 14.05.2013

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

vasjn23
Offline
Зарегистрирован: 14.05.2013

Всё!!! получилось!!!!

int latchPin = 5;
int clockPin = 6;
int dataPin = 4;
 
char leds = 0;
 
void setup() 
{
  pinMode(latchPin, OUTPUT);
  pinMode(dataPin, OUTPUT);  
  pinMode(clockPin, OUTPUT);
}
 
void loop() 
{
  leds = 0;
    delay(500);
  for (int i = 15; i >-1; i--)
  {
    registerWrite(i, HIGH);
    delay(500);
  }
  delay(500);
  for (int i=15; i >= 0; i--)
  {
    registerWrite(i, LOW);
    delay(500);
  }
}
void registerWrite(int whichPin, int whichState) {
  // для хранения 16 битов используем unsigned int
  static unsigned int bitsToSend = 0;   
 
  // выключаем светодиоды на время передачи битов
  digitalWrite(latchPin, LOW);
 
  // устанавливаем HIGH в соответствующий бит
  bitWrite(bitsToSend, whichPin, whichState);
 
  // разбиваем наши 16 бит на два байта
  // для записи в первый и второй регистр
  byte registerTwo = highByte(bitsToSend);
  byte registerOne = lowByte(bitsToSend);
 
  // "проталкиваем" байты в регистры
  shiftOut(dataPin, clockPin, MSBFIRST, registerTwo);
  shiftOut(dataPin, clockPin, MSBFIRST, registerOne);
 
  // "защелкиваем" регистр, чтобы биты появились на выходах регистра
  digitalWrite(latchPin, HIGH);
}

Теперь понятно - почему не оставалось всечение. Код на всякий случай - может кому пригодиться.

Теперь буду крутить кнопки - аж 2 штуки!!!

leshak
Offline
Зарегистрирован: 29.09.2011

vasjn23 пишет:

Теперь буду крутить кнопки - аж 2 штуки!!!

Ага. Только в следующий раз постарайтесь темы называть более информативно/уникально.

"помогите", "новичок", "проблема с программой" - такое название можно дать 95% темам. Но это же не повод называть все одинаково. Ориентировать не возможно. Вот код вы выложили - но никто же его не найдет :(

Что-то типа "бегущая волна на сдвиговом регистре" - было бы более "говоряще" :)

А то что "проблемы", "новичок" и "нужна помощь" - так это и так самоочевидно :)

vasjn23
Offline
Зарегистрирован: 14.05.2013

Тут отпираться не буду, но в своё оправдание скажу - что когда тему создавал - то я же не знал - куда меня кривая выведет... А вдрух не получилось - бы ничего.  И тогда бы еще больше всех запутал. Я думаю администраторы могут смело поменять тему - как вариант на "Сдвиговые регистры 74СН959 или куда бежит светодиод?" ну или как то так - я не знаю. Еще раз спасибо за советы...

vasjn23
Offline
Зарегистрирован: 14.05.2013

Новый день - новые свешения, новый код. 

Прикрутил я кнопку - прописал, поставил условие if ( вход низкий, тогда true)? НО условие игнорируется, и программа работат без нажатия. А у меня задача - чтобы отработала 1 цикл - и дальше ждала нажатия кнопки. Где промахнулся??? Вроде по структуре ошибок не допускал?

 

int latchPin = 5;
int clockPin = 6;
int dataPin = 4;
int buttonApin = 9;

byte leds = 0;

void setup() 
{
  pinMode(latchPin, OUTPUT);
  pinMode(dataPin, OUTPUT);  
  pinMode(clockPin, OUTPUT);
  pinMode(buttonApin, INPUT_PULLUP);
}

void loop() 
{
  if (digitalRead(buttonApin) == LOW);
  {
    for (int i = 15; i >-1; i--)// подъем светодиодного свечения (набор)
    {
      registerWrite(i, HIGH);
      delay(500);
    }
    delay(10000); // задержка в режиме полного свечения
    for (int i=15; i >= 0; i--)// отключение по 1-й штуке
    {
      registerWrite(i, LOW);
      delay(500);
    }
  }
}
void registerWrite(int whichPin, int whichState) {
  // для хранения 16 битов используем unsigned int
  static unsigned int bitsToSend = 0;// делаем величину постоянной для сохранения состояния между переключениями

  // выключаем светодиоды на время передачи битов
  digitalWrite(latchPin, LOW);

  // устанавливаем HIGH в соответствующий бит
  bitWrite(bitsToSend, whichPin, whichState);

  // разбиваем наши 16 бит на два байта
  // для записи в первый и второй регистр
  byte registerTwo = highByte(bitsToSend);
  byte registerOne = lowByte(bitsToSend);

  // "проталкиваем" байты в регистры
  shiftOut(dataPin, clockPin, MSBFIRST, registerTwo);
  shiftOut(dataPin, clockPin, MSBFIRST, registerOne);

  // "защелкиваем" регистр, чтобы биты появились на выходах регистра
  digitalWrite(latchPin, HIGH);
}

 

vasjn23
Offline
Зарегистрирован: 14.05.2013

Разобрался! Ошибочка со знаком припинания после if точка с запятой не нужна.

vasjn23
Offline
Зарегистрирован: 14.05.2013

хочу добавить регулировку я ркости  - делаю вот так:

int latchPin = 5;
int clockPin = 6;
int dataPin = 4;
int outputEnablePin = 11; 
byte leds = 0;
int ButtonPin =8;
byte b = 15;

void setup() 
{
  pinMode(latchPin, OUTPUT);
  pinMode(dataPin, OUTPUT);  
  pinMode(clockPin, OUTPUT);
  pinMode(outputEnablePin, OUTPUT);
  pinMode(ButtonPin, INPUT_PULLUP);

}
void loop() 
{
  setBrightness(b);
  leds = 0;// начальное состояние - 0-й выход.
  updateShiftRegister();// запись в регистр
  delay(500);// задержка
  for (int i = 0; i <=7; i++)//начинаем считать по условию
  {
    bitSet(leds, i);// сначала зажигаем в 1
    updateShiftRegister();// обновляем
    delay(500);// задержка
  }
  if (digitalRead(ButtonPin)==LOW)
  {
    b=b+15;
    if (b > 255) b=0;
    setBrightness(b);
    delay(50);
  }

  delay(500);// задержка общего свечения
  for (int i = 0; i <=7; i++)// начинаем гасить по одному
  {
    bitClear(leds, i);// гасим
    updateShiftRegister();// обновляем
    delay(500);// задержка
  }
}
void updateShiftRegister()
{
  digitalWrite(latchPin, LOW);
  shiftOut(dataPin, clockPin, LSBFIRST, leds);
  digitalWrite(latchPin, HIGH);
}

void setBrightness(byte brightness)
{
  analogWrite(outputEnablePin, brightness);
}

а регулировка не происходит - такое ощущение, что она опросник кнопки просто проходит. Что не правильно сделал?

 

Если на 32 строке вставить код

digitalWrite (ledPin,HIGH);
    delay(1000);
    digitalWrite(ledPin,LOW);

светодиод включается и выключается  - значит кнопку видит, НО почему-то не между циклами ( при полном включенном состоянии) , а после полного прохождения. В чем тут подвох - ведь по тексту стоит так, что-б ыотрегулировать яркость - когда все светодиоды ключены?

vasjn23
Offline
Зарегистрирован: 14.05.2013

Блин, классный форум! Сам српосил - сам ответил. Успеваю решить вопрос ДО того как кто-то вмешается... А прога выше работает...