Коль поможете мне разобраться в библиотеке ShiftRegister75HC595

UserDead
UserDead аватар
Offline
Зарегистрирован: 29.11.2015

Доброго времени суток уважаемые.

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

Библиотека любезно предоставлена забугоным парнем отсюда http://shiftregister.simsso.de/

Собственно начав ей пользоваться я получил то что мне нужно. Указываешь пин например 35-й и тебе на 35-м выводе синал (3-й пин пятого регистра если считать от 1)

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

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

void ShiftRegister74HC595::set(int pin, uint8_t value) {
    if (value == 1)
        _digitalValues[pin / 8] |= 1 << (pin % 8);
    else
        _digitalValues[pin / 8] &= ~(1 << (pin % 8));
                                     
    setAll(_digitalValues);
}

Она так и называется sr.set(pin, value);

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

Тут у нас массив. Адрес ячейки который непонятно зачем делиться на 8. Понятно что вычисляется ячейка в массиве этим делением но зачем именно делить я не понял. А вы? Дальше то что определяется равно значение единице или нет понятно. а вот символ символы |= и << я не понял. И информации как таковой не нашел. А вот с кусочком (pin % 8) мне все понятно. Это модульный делитель и он делит определение конкретного пина микросхемы. Но как он ее находит. Микросхему эту. Второй это или третий сдвиговик мне не ясно.

Все косточки здесь : https://github.com/Simsso/Shift-Register-74HC595-Arduino-Library/blob/master/ShiftRegister74HC595.cpp

Кто что подскжет?

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

сбросить или установить пин - вычисляем ( по номеру пина ) какой это номер регистра
                                        - вычисляем ( по номеру пина ) какой это пин в регистре
                                        - сбрасываем или устанавливаем пин , перезаписываем все регистры 

Адрес ячейки который непонятно зачем делиться на 8.
- это определение номера регистра , в котором сидит нужный пин

А вот с кусочком (pin % 8) мне все понятно. Это модульный делитель и он делит определение конкретного пина микросхемы. Но как он ее находит. 

- это определение номера в рамках вычисленного регистра

|= 1 << (pin % 8);
- установка пина в 1

&= ~(1 << (pin % 8));
- сброс пина в 0

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

три регистра по 8 пинов , всего = 24
 

нужно изменить состояние пина 19....
19 / 8 = 2 , второй регистр
19 % 8 = 3 , третий пин второго регистра

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

в
ShiftRegister74HC595::ShiftRegister74HC595(int numberOfShiftRegisters, int serialDataPin, int clockPin, int latchPin)
правильно задал значение
int numberOfShiftRegisters
?

UserDead
UserDead аватар
Offline
Зарегистрирован: 29.11.2015

Благодарю за ответ. Стало понятно что деля на 8 он считает номер регистра с 0. Т.е. 1-й это нулевой регистр. Ответ напросился сам.

Меня ввели в заблуждение неизвестные мне операнды |= и &= (или равно, и равно...) а еще этот << как бы добавление \ замещение. Запутался. Но то что нужно было понять, я понял.

UserDead
UserDead аватар
Offline
Зарегистрирован: 29.11.2015

У меня физически их 8, я там и указал 8.

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

_digitalValues[pin / 8] |= 1 << (pin % 8);

в байте номер "pin / 8" пин "pin % 8" установить в 1

....... |= 1 << (pin % 8); - это прелести С++

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

_digitalValues[pin / 8] |= 1 << (pin % 8);

это >>>>>>>>>>>>

_digitalValues[pin / 8] = _digitalValues[pin / 8] | ( 1 << (pin % 8) );

|= , &= - это тоже прелести С++

 

UserDead
UserDead аватар
Offline
Зарегистрирован: 29.11.2015

Похоже на двухстороннюю функцию. Автор так все исскусно сократил.

Теперь все понятно. Еще раз спасибо!

orcsin
Offline
Зарегистрирован: 12.06.2015

UserDead, спасибо за ссылку, 3 дня голову ломаю как лучше это сделать и либу не мог найти, дома проверю :)

 

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011

Нет.
Засылаете все байты (меняя нужные биты) и выводите их.
И так каждое изменение.

orcsin
Offline
Зарегистрирован: 12.06.2015

Ага я понял по коду либы, что она ни чего не делает того чего я хочу.

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

orcsin
Offline
Зарегистрирован: 12.06.2015

Будет так работать 595?

1. устанавливаем синхронизацию "защелки" на LOW

2. Циклом For загоняем по очереди 8 значений масива в 595

shiftOut(dataPin, clockPin, MSBFIRST, arr[i]);

3. "защелкиваем" регистр, тем самым устанавливая значения на выходах

UserDead
UserDead аватар
Offline
Зарегистрирован: 29.11.2015

Интересно стало что вам нужно от бибилиотеки. Я вот запутался в свой задаче что полез в реализацию библиотеки. Разобрался и пришел к выводу что все таки косяк был в железе и чуток в софте. Если бы она работала не так как нужно мне пришлось бы переписывать на свою функцию. Я примерно имею представление но до этого не дошло. 

Сэкономню я ка немного нервишек и дальше юзаю библиотеку. 

UserDead
UserDead аватар
Offline
Зарегистрирован: 29.11.2015

Не сильно много кода повторять ShoftOut?!

Ну кому как. Я думаю реализация в библитеке вполне таки практичная. А ненужные функции (если действительно не нужные типа sr.setAllHIGH(); sr.getState(pin); ) То и вырезать можно из CPP файла и место тем самым сЭкономить)) 

orcsin
Offline
Зарегистрирован: 12.06.2015

что то не работает эта либа у меня или я что то не понимаю. У меня двое последовательных 595. ВОт код:

//Пин подключен к ST_CP входу 74HC595 latchPin
//int latchPin = 13;
//Пин подключен к SH_CP входу 74HC595 clockPin
//int clockPin = 12;
//Пин подключен к DS входу 74HC595 dataPin
//int dataPin = 8;

#include <ShiftRegister74HC595.h>

// create shift register object (number of shift registers, data pin, clock pin, latch pin)
ShiftRegister74HC595 sr (2, 8, 12, 13); 

void setup() {
}

void loop() {
  sr.setAllHigh(); // set all pins HIGH
  delay(500);
  
  sr.setAllLow(); // set all pins LOW
  delay(500);
}

я так понимаю этот код должен мигать всеми выходами через пол секунды. Но что то ноль реакции, что может быть не так? распиновка 100% правильная.

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

определи пины 8 , 12 , 13 как выходы ( по умолчанию все пины - входы )

orcsin
Offline
Зарегистрирован: 12.06.2015

либа всё делает за нас :)

ShiftRegister74HC595.h

// constructor
ShiftRegister74HC595::ShiftRegister74HC595(int numberOfShiftRegisters, int serialDataPin, int clockPin, int latchPin)
{
    // set attributes
    _numberOfShiftRegisters = numberOfShiftRegisters;
    
    _clockPin = clockPin;
    _serialDataPin = serialDataPin;
    _latchPin = latchPin;
    
    // define pins as outputs
    pinMode(clockPin, OUTPUT);
    pinMode(serialDataPin, OUTPUT);
    pinMode(latchPin, OUTPUT);

 

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

а если уйти от 13-го пина ? на 11-ый , например....

UserDead
UserDead аватар
Offline
Зарегистрирован: 29.11.2015

Я осмелюсь взять на себя отвественность запросить фото разводной части вашей платы с двух сторон. Ну не может быть такого что распиновка вернаи и не работает. Сам вчера мучался и понял что последние три микры неправильно подключены. Хотя тоже был на 100 уверен. Или перепроверьте сами. ST и SH на всех микрах запаралелены. DS и Q7' легче наизусть выучить по расположению. А для надежности каждую микру можно прозвонить по паралельности ST и SH цепей. Я вообще мучался так: Находил DS а SH и ST тыком искал меняя значения переменных, но знал что они на конкретных пинах запаяны лично мной.

Оно без разницы на каких пинах У меня 4 3 2 пины который 4 - DS. Работает. 

Еще нюанс Есть же еще выводы MR и OE с ними тоже надо быть внимательнее. Один знаю питается на Vcc другой на Gnd .

Он: http://arduino.ru/Tutorial/registr_74HC595

10 и 13-й пины. Безних не работает. Мб похожая ситуация?! А как насчет кондера в цепи. для стабилизации вроде.

Помните, TTL логика. Питание не просаживается ниже логического? Мб из-за этого например на выводе MR он в постоянно сброшенном виде. Было и такое.

orcsin
Offline
Зарегистрирован: 12.06.2015

ни чего не даёт.

orcsin
Offline
Зарегистрирован: 12.06.2015

кондёр стоит. всё на месте и всё хорошо работает этим кодом так что микрухи работают 100 % и подключено тоже всё правильно, а либа где то тупит...

//Пин подключен к ST_CP входу 74HC595 latchPin
int latchPin = 13;
//Пин подключен к SH_CP входу 74HC595 clockPin
int clockPin = 12;
//Пин подключен к DS входу 74HC595 dataPin
int dataPin = 8;
 
byte adr = 0b11111111;
byte mask = 0b10101010;
byte result;
 
void setup() {
  //устанавливаем режим OUTPUT
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  Serial.begin(9600);
}
 
void loop() {
    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin, MSBFIRST, adr);
    shiftOut(dataPin, clockPin, MSBFIRST, adr);
    digitalWrite(latchPin, HIGH);
    Serial.println("adr");
    Serial.println(adr);
    delay(500);
    
    digitalWrite(latchPin, LOW);
    result = adr & mask;
    shiftOut(dataPin, clockPin, MSBFIRST, result);
    shiftOut(dataPin, clockPin, MSBFIRST, result);
    digitalWrite(latchPin, HIGH);
    Serial.println("result");
    Serial.println(result);
    delay(500);
}

 

UserDead
UserDead аватар
Offline
Зарегистрирован: 29.11.2015

Включите подробный вывод при компиляции в настройках. Мб ошибки есть. 

(Файл, Настройки, Показать подробный вывод две галочки)

orcsin
Offline
Зарегистрирован: 12.06.2015

UserDead, смотрю я на код либы и не до конца понимаю что она делает...

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

Допустим сейчас на выходах есть значения 00110101 и я хочу 4 значение перевести из 1 в 0. Остальные значения должна остаться на месте. Она это умеет и где она это делает в либе?

UserDead
UserDead аватар
Offline
Зарегистрирован: 29.11.2015

Да. Именно так. Она запоминает значения состояния других выводов и меняет те что вы указываете в переменной pin. Я прямо сейчас работаю с устройством с этой библиотекой. Хранит она все в массиве digitalValues

Вот исполняемый кусочек

void ShiftRegister74HC595::setAll(uint8_t * digitalValues) {   //сама функция записи данных в регистры
    int byte; //инициализируем переменную типа integer для счетчика
    for (byte = 0 ; byte < _numberOfShiftRegisters; byte++) //цикл где вы присваиваем переменной счетчика 0 и повторяем цикл столько раз сколько у нас регистров (задается в инициализации библиотеки в вашем коде.
        shiftOut(_serialDataPin, _clockPin, MSBFIRST, digitalValues[byte]); //передает данные в регистры из массива digitalValues (если не знакомы с массивами - познакомьтесь.
    
    _digitalValues = digitalValues;  //редирект переменной (неважно по сути)
    
    digitalWrite(_latchPin, HIGH); //щелкаем выводами для синхронизации именно вконце чтобы не резать 8-ми битные пакеты.
    digitalWrite(_latchPin, LOW); 
}

void ShiftRegister74HC595::set(int pin, uint8_t value) {  //функция установки. запускается ПЕРЕД тем что вверху. мы ее собственно и вызываем sr.set(pin, state);
    if (value == 1)  //определяем что мы задаем в порт HI или LO (1 и 0 эквалиентно)
        _digitalValues[pin / 8] |= 1 << (pin % 8); //В массив ячейкой которой является вычисление номера регистра деля его на 8 записывается значение 1 или 0 в зависимости что хотим. А в конкретный диапазон отдельной микросхемы к примеру 8-16 (вторая микросхема) вычисляется номер микросхемы в по модулю % 8 (детали выше, мне уже пояснили)
    else
        _digitalValues[pin / 8] &= ~(1 << (pin % 8)); //Тоже самое только про ноль.
 }

Вкратце ответ. Да, и да.

orcsin
Offline
Зарегистрирован: 12.06.2015

Спасибо за разъяснение моя ошибка крылась в том, что я думал что _numberOfShiftRegisters это количество микросхем :) а не физических выводов :) И ставя 2 я использовал только первые два регистра :)

orcsin
Offline
Зарегистрирован: 12.06.2015

всё равно что то не так!!!

Вот код который работает

//Пин подключен к ST_CP входу 74HC595 latchPin
int latchPin = 11;
//Пин подключен к SH_CP входу 74HC595 clockPin
int clockPin = 12;
//Пин подключен к DS входу 74HC595 dataPin
int dataPin = 8;
 
byte adr = 0b11111111;
byte mask = 0b00000000;
byte result;
 
void setup() {
  //устанавливаем режим OUTPUT
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);;
}
 
void loop() {
    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin, MSBFIRST, adr);
    shiftOut(dataPin, clockPin, MSBFIRST, adr);
    digitalWrite(latchPin, HIGH);
    delay(500);
    
    digitalWrite(latchPin, LOW);
    result = adr & mask;
    shiftOut(dataPin, clockPin, MSBFIRST, mask);
    shiftOut(dataPin, clockPin, MSBFIRST, mask);
    digitalWrite(latchPin, HIGH);
    delay(500);
}

а вот этот не работает

//Пин подключен к ST_CP входу 74HC595 latchPin
//int latchPin = 13;
//Пин подключен к SH_CP входу 74HC595 clockPin
//int clockPin = 12;
//Пин подключен к DS входу 74HC595 dataPin
//int dataPin = 8;

#include <ShiftRegister74HC595.h>

// create shift register object (number of shift registers, data pin, clock pin, latch pin)
ShiftRegister74HC595 sr (16, 8, 12, 11); 

void setup() {
  sr.set(9, HIGH); // set single pin HIGH
}

void loop() {
  sr.setAllHigh(); // set all pins HIGH
  delay(500);
  
  sr.setAllLow(); // set all pins LOW
  delay(500); 

}

что я делаю не так?

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

точно  ShiftRegister74HC595 sr (16, 8, 12, 11); 16 регистров подключено ?
может быть 2 регистра и пинов управляемых от них = 16 ?

orcsin
Offline
Зарегистрирован: 12.06.2015

SU-27-16, я теперь опять начинаю путаться :)

подключенно по этой схеме

orcsin
Offline
Зарегистрирован: 12.06.2015

так тоже не работает

ShiftRegister74HC595 sr (2, 8, 12, 11);

UserDead
UserDead аватар
Offline
Зарегистрирован: 29.11.2015

В первой переменной указывается количество регитсров. Кол-во выводов он и так знает на основе количества регистров. Если регистра 2 то указать надо 2. Включите вывод логов. Мб Что-то не так. Ну не может быть на ровном месте не работать на таком простом примере.

Количество пинов НЕ указывается в инициализации.

UserDead
UserDead аватар
Offline
Зарегистрирован: 29.11.2015

Методом тыка не пробовали ради прикола поменять местами ST и SH хоть что-то есть на выходах?

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

orcsin ,    какой регистр второму передаёт сдвиг информации - не перепутал ?
выводы DS и Q7'.......

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

фантастика....
сделай на одном регистре... для проверки....

orcsin
Offline
Зарегистрирован: 12.06.2015

я выше показывал код простой, и все диоды на обоих 595 работают

//Пин подключен к ST_CP входу 74HC595 latchPin
int latchPin = 11;
//Пин подключен к SH_CP входу 74HC595 clockPin
int clockPin = 12;
//Пин подключен к DS входу 74HC595 dataPin
int dataPin = 8;
 
byte adr = 0b11111111;
byte mask = 0b00000000;
byte result;
 
void setup() {
  //устанавливаем режим OUTPUT
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);;
}
 
void loop() {
    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin, MSBFIRST, adr);
    shiftOut(dataPin, clockPin, MSBFIRST, adr);
    digitalWrite(latchPin, HIGH);
    delay(500);
    
    digitalWrite(latchPin, LOW);
    result = adr & mask;
    shiftOut(dataPin, clockPin, MSBFIRST, mask);
    shiftOut(dataPin, clockPin, MSBFIRST, mask);
    digitalWrite(latchPin, HIGH);
    delay(500);
}

два раза шифтаут делаю что бы прошло 8+8 значений. и всё работает

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

померяйся пипис.... , ой , библиотеками с UserDead - откуда он скачал...

может быть у тибя глЮчьная библа ? ( бывает )

UserDead
UserDead аватар
Offline
Зарегистрирован: 29.11.2015

Мде. Я качал с gitHub так что ему тоже советую. На оф сайте есть ссылка на него. Мне кажется он где-то косячит. ВОт нИверю я в его избранность. У меня работает (и как понимаю у большинства) у него нет.

orcsin
Offline
Зарегистрирован: 12.06.2015

щас попробую в протеусе повторить

orcsin
Offline
Зарегистрирован: 12.06.2015

проэмулировал в Протеусе. Не заработало :(

по схеме поставил кондёр 1 mF, удалил его - заработало, поставил 1nF тоже работает.

Есть у меня большое подозрение что я не тот кондёр поставил :) Протеус при кондёре выше 100nF перестаёт работать, видимо что то знает :) завтра выпаяю его и посмотрю.

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

дык , блииин !!!!!!
1 mF - валит фронты сигнала .....

orcsin
Offline
Зарегистрирован: 12.06.2015

убрал кондёр, теперь начало хоть как то работать, то есть мигать, НО что то не понятно. Использую вот этот код

#include <ShiftRegister74HC595.h>

// create shift register object (number of shift registers, data pin, clock pin, latch pin)
ShiftRegister74HC595 sr (2, 8, 12, 11); 
 
void setup() { 
}

void loop() {

  sr.setAllHigh(); // set all pins HIGH
  delay(250);
  
  sr.setAllLow(); // set all pins LOW
  delay(250); 
}

Но поотдельности пины работать не хотят :(

orcsin
Offline
Зарегистрирован: 12.06.2015

А так не работает, хотя по сути это же одно и тоже. Что не так?

#include <ShiftRegister74HC595.h>

// create shift register object (number of shift registers, data pin, clock pin, latch pin)
ShiftRegister74HC595 sr (15, 8, 12, 11); 
 
void setup() { 
}

void loop() {

  sr.setAllLow(); // set all pins LOW
  delay(500); 
  
  sr.set(0, HIGH); // set single pin HIGH
  sr.set(1, HIGH); // set single pin HIGH
  sr.set(2, HIGH); // set single pin HIGH
  sr.set(3, HIGH); // set single pin HIGH
  sr.set(4, HIGH); // set single pin HIGH
  sr.set(5, HIGH); // set single pin HIGH
  sr.set(6, HIGH); // set single pin HIGH
  sr.set(7, HIGH); // set single pin HIGH
  sr.set(8, HIGH); // set single pin HIGH
  sr.set(9, HIGH); // set single pin HIGH
  sr.set(10, HIGH); // set single pin HIGH
  sr.set(11, HIGH); // set single pin HIGH
  sr.set(12, HIGH); // set single pin HIGH
  sr.set(13, HIGH); // set single pin HIGH
  sr.set(14, HIGH); // set single pin HIGH
  sr.set(15, HIGH); // set single pin HIGH

  // sr.setAllHigh(); // set all pins LOW
  delay(500); 
}

 

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011

SU-27-16 пишет:

дык , блииин !!!!!!
1 mF - валит фронты сигнала .....

А кондёр на латч зачем?

orcsin
Offline
Зарегистрирован: 12.06.2015

Не знаю уже, вник всё что можно было, но эта либа не работает у меня как должна, но при этом код 2.2. от сюда работает отлично

http://arduino.ru/Tutorial/registr_74HC595. В принципе из 2.2 можно сделать нужную функцию или вобще сделать либу, хотя и та очень хорошо написана, но где подводный камень найти не могу :(

UserDead
UserDead аватар
Offline
Зарегистрирован: 29.11.2015

Если не ошибаюсь. Я в своем проекте использую счет от 1 до 8. Если мне надо включить Q0 я пишу 1.

Нет не ошибаюсь, проверил.

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011

orcsin пишет:

А так не работает, хотя по сути это же одно и тоже. Что не так?

#include <ShiftRegister74HC595.h>

// create shift register object (number of shift registers, data pin, clock pin, latch pin)
ShiftRegister74HC595 sr (15, 8, 12, 11); 
 

Шифт регистр- жто микросхема памяти с последовательным входом и параллельным выходом.
Регистр имеет ёмкость 1 байт то есть 8 бит.
Вы пытаетесь подключить 15 регистров, 15 микросхем, 120 разрядов.
Впечатление что в библиотеке есть ограничение на их количество.
Вы путаете количество регистров с их суммарной разрядностью.
Поставьте вместо 15-ти двойку.

UserDead
UserDead аватар
Offline
Зарегистрирован: 29.11.2015

И действительно. Я что-то не заметил. Блин ну так сложно перевести строки в коммертаниях. Так я переведу:

//создание объекта сдвигового регистра (кол-во сдвиговых регистров, пин данных, пин синхронизации, пин защелки)

Типичное недопонимание функций. Так зачем было при выставлении sr.set менять количество сдвиговиков ошибочно принимая их за выводы. написано number of shift registers. Блин

Что-то сомневаюсь на ограничение по количеству регистров. Какая разница сколько их, все сидят на цепочке, только время задвигания данных сыграет роль. Ну и да, память переменной в которой храниться значения состояний. А он в uint8_t. Сколько там ограничение?! 32767

orcsin
Offline
Зарегистрирован: 12.06.2015

Пробовал я и 2 и 16 писать, ну не хочет.

Вобщем я использовал код 2.2 из http://arduino.ru/Tutorial/registr_74HC595

Работает как часики и меня устраивает.