Arduino uno + ethernet shield W5100 + 74HC595N в каскаде из 3х
- Войдите на сайт для отправки комментариев
Вс, 31/07/2016 - 18:48
Добрый день.
Недавно начал изучать Arduino.
Построил каскад из 3х 74HC595N - без ethernet shield W5100 работают как надо по коду:
//Пин подключен к ST_CP входу 74HC595
const int latchPin = 8;
//Пин подключен к SH_CP входу 74HC595
const int clockPin = 12;
//Пин подключен к DS входу 74HC595
const int dataPin = 11;
void setup() {
pinMode(latchPin, OUTPUT);
pinMode(dataPin, OUTPUT);
pinMode(clockPin, OUTPUT);
}
void registerWrite(int whichPin, int whichState) {
// для хранения 32 битов используем unsigned int
unsigned int bitsToSend[3] = {0,0,0};
// выключаем светодиоды на время передачи битов
digitalWrite(latchPin, LOW);
// устанавливаем HIGH в соответствующий бит
bitWrite(bitsToSend[whichPin/8], whichPin%8, whichState);
for(int i = 0; i < 3; i++) shiftOut(dataPin, clockPin, MSBFIRST, bitsToSend[i]);
// "защелкиваем" регистр, чтобы биты появились на выходах регистра
digitalWrite(latchPin, HIGH);
}
void loop() {
registerWrite(13, HIGH);
}
При попытке написать скетч для управления светодиодами через ethernet shield W5100 управление не работает\
#include <SPI.h>
#include <Ethernet.h>
byte mac[] = {0xDE, 0x24, 0xF7, 0xDD, 0x23, 0x7B};
byte ip[] = {172,17,7,112};
EthernetServer server(80);
EthernetClient client;
int WAIT = 300;
#define bufferMax 128
int bufferSize;
char buffer[bufferMax];
String readString = String(128);
char post;
//Пин подключен к ST_CP входу 74HC595
const int latchPin = 8;
//Пин подключен к SH_CP входу 74HC595
const int clockPin = 6;
//Пин подключен к DS входу 74HC595
const int dataPin = 7;
void setup() {
pinMode(latchPin, OUTPUT);
pinMode(dataPin, OUTPUT);
pinMode(clockPin, OUTPUT);
Serial.begin(9600);
Serial.println("device is run");
Ethernet.begin(mac, ip);
server.begin();
}
void registerWrite(int whichPin, int whichState) {
// для хранения 16 битов используем unsigned int
unsigned int bitsToSend[3] = {0,0,0};
// выключаем светодиоды на время передачи битов
digitalWrite(latchPin, LOW);
// устанавливаем HIGH в соответствующий бит
bitWrite(bitsToSend[whichPin/8], whichPin%8, whichState);
for(int i = 0; i < 3; i++) shiftOut(dataPin, clockPin, MSBFIRST, bitsToSend[i]);
// "защелкиваем" регистр, чтобы биты появились на выходах регистра
digitalWrite(latchPin, HIGH);
}
void loop() {
registerWrite(2, HIGH);
EthernetClient client = server.available();
if (client)
{
// Проверяем подключен ли клиент к серверу
while (client.connected())
{
char c = client.read();
if (readString.length() < 30) {
readString += c;
}
if (c == '\n') { if(readString.indexOf("p=1") > 0) {
Serial.println("device is on");
registerWrite(1, HIGH);
registerWrite(5, HIGH);
}
if(readString.indexOf("p=0") > 0) {
Serial.println("device is off");
registerWrite(1, HIGH);
registerWrite(2, HIGH);
}
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println();
client.println("<!DOCTYPE html>");
client.println("<html lang=\"ru\">");
client.println("<head>");
client.println("<meta charset=\"UTF-8\">");
client.println("<title>Home</title>");
client.println("</head>");
client.println("<body>");
client.println("Устройство:");
client.println("<br>");
client.println("<a href=\"?p=0\">Выкл</a>");
client.println(" <a href=\"?p=1\">Вкл</a>");
client.println("</body>");
client.println("</html>");
readString="";
client.stop(); }
}
} }
Помогите разобраться с этим. В какую сторону копать?
Скетч неполный, так Вы сами себе злобный буратино - не нужна помощь, как хотите.
Рискну предположить, что у Вас оба девайса и W5100, и 74HC595N сидят на SPI и подрались между собой либо за пины, либо за master/slave, либо ещё за что-нибудь. Вот туда и копайте.
Евгений, скетч второй поправлю, он с ошибками,
А, вам, спасибо за подсказку. Видимо там конфликт в SPI master\SLAVE
Код у меня сейчас такой:
#include <SPI.h> #include <Ethernet.h> byte mac[] = {0xDE, 0x24, 0xF7, 0xDD, 0x23, 0x7B}; byte ip[] = {172,17,7,112}; EthernetServer server(80); EthernetClient client; //Пин подключен к ST_CP входу 74HC595 const int latchPin = 8; //Пин подключен к SH_CP входу 74HC595 const int clockPin = 6; //Пин подключен к DS входу 74HC595 const int dataPin = 7; void setup() { pinMode(latchPin, OUTPUT); pinMode(dataPin, OUTPUT); pinMode(clockPin, OUTPUT); Serial.begin(9600); Serial.println("device is run"); Ethernet.begin(mac, ip); server.begin(); } void registerWrite(int whichPin, int whichState) { // для хранения 16 битов используем unsigned int unsigned int bitsToSend[3] = {0,0,0}; // выключаем светодиоды на время передачи битов digitalWrite(latchPin, LOW); // устанавливаем HIGH в соответствующий бит bitWrite(bitsToSend[whichPin/8], whichPin%8, whichState); for(int i = 0; i < 3; i++) shiftOut(dataPin, clockPin, MSBFIRST, bitsToSend[i]); // "защелкиваем" регистр, чтобы биты появились на выходах регистра digitalWrite(latchPin, HIGH); } void loop() { EthernetClient client = server.available(); if (client) { // Проверяем подключен ли клиент к серверу while (client.connected()) { char c = client.read(); if (readString.length() < 30) { readString += c; } if (c == '\n') { if(readString.indexOf("p=1") > 0) { Serial.println("leds 1 and 5 ON"); registerWrite(1, HIGH); registerWrite(5, HIGH); } if(readString.indexOf("p=0") > 0) { Serial.println("leds 1 and 5 ON"); registerWrite(1, HIGH); registerWrite(2, HIGH); } client.println("HTTP/1.1 200 OK"); client.println("Content-Type: text/html"); client.println(); client.println("<!DOCTYPE html>"); client.println("<html lang=\"ru\">"); client.println("<head>"); client.println("<meta charset=\"UTF-8\">"); client.println("<title>Home</title>"); client.println("</head>"); client.println("<body>"); client.println("Устройство:"); client.println("<br>"); client.println("<a href=\"?p=0\">Первое положение</a>"); client.println(" <a href=\"?p=1\">Второе положение</a>"); client.println("</body>"); client.println("</html>"); readString=""; client.stop(); } } } }Так как W5100 и 74HC595N работают по SPI, то правильно я понимаю? что на 74HC595N мне надо передавать в режиме slave?
Они оба слейвы на SPI. Чтобы не разбираться, где они конфликтуют, выносите 74HC595N на свободные пины и делайте софтовый SPI, благо протокол простейший -- подняли ногу SCK -> выставили значение очередного бита на ногу MOSI -> опустили ногу SCK -- передача бита состоялась.
Думаю ваш вариант не подойдет.
У меня основная задача - иметь платформу по подключению большого числа светодиодов, который каждый в отдельности может управляться через POST.
Вообще в идеале нужно открывать файл на удаленном сервере, писать его на SD-карту, а потом уже парся строку из файла подавать биты на различные ножки.
Я понимаю, что задача не тревиальная, но реализовать ее же можно.
Можно узнать, почему?
Софтовый SPI конечно медленнее аппаратного, но зато с выносом туда регистров, можно будет использовать оба интерфейса одновременно. Если же один аппаратный SPI будет использоваться и для связи с шилдом и для передачи данных регистрам, то оба устройства будут получать доступ к интерфейсу по очереди.
Карта тоже по SPI обычно подлкючается. Тогда всем трем устройствам придется ждать друг друга.
Да не сказал бы я, что такая уж нетривиальная.
Бред какой-то...
М/К и так один поток только обрабатывает, тут в любом случае одновременно работать езернет и 74HC595N НЕ БУДУТ В ПРИНЦИПЕ. Разделять устройства на разные пины не нужно. Это может только критично, если одно устройство может вызыватся внутри прерывания в момент, когда идет обращение к другому устройству - только в этом случае может быть коллизия. В данном случае в данной задаче этого нет.
Нужно просто правильно выбирать через CS нужное устройство при обращении к нему.
Что-то я совсем запутался.
Для работы через аппаратный SPI нужно подключать библиотеку и передавать данные через SPI.transfer()
А для программного SPI, что нужно?
Для чего client описан глобально в строке 6 (блин, вставляйте код правильно - как без номеров обсуждать?), а потом в функции loop он же описан локально. Вы понимаете. что он не глобален? и в loop каждый раз новый создаётся?
На сдвиговый регистр Вы всегда передаёте только в режиме master, т.к. именно Вы иницируете передачу. а не сдвиговый регистр - ему-то это зачем?
Я код перепишу и выложу нормальном виде.
А вот по вашему высказыванию
"На сдвиговый регистр Вы всегда передаёте только в режиме master, т.к. именно Вы иницируете передачу. а не сдвиговый регистр - ему-то это зачем?"
можете дать более подробное объяснение?
Переписал код основываясь на исходнике из интернета.
#include <Ethernet.h> #include <SPI.h> boolean incoming = 0; // ниже необходимо ввести MAC адрес и IP адрес вашего контроллера. // IP адрес будет зависеть от вашей локальной сети: byte mac[] = { 0xDE, 0x24, 0xF7, 0xDD, 0x23, 0x7B }; IPAddress ip(172, 17, 7, 112); //<<< ВВЕДИТЕ ВАШ IP АДРЕС В ЭТОЙ СТРОКЕ!!! // Инициализация библиотеки Ethernet server library // с использованием IP адреса и порта, который вы указали // (по умолчанию HTTP порт устанавливается на 80): EthernetServer server(80); //Пин подключен к ST_CP входу 74HC595 const int latchPin = 8; //Пин подключен к SH_CP входу 74HC595 const int clockPin = 6; //Пин подключен к DS входу 74HC595 const int dataPin = 7; void setup() { pinMode(latchPin, OUTPUT); pinMode(dataPin, OUTPUT); pinMode(clockPin, OUTPUT); // запуск Ethernet подключения и сервера: Ethernet.begin(mac, ip); server.begin(); Serial.begin(9600); } void registerWrite(int whichPin, int whichState) { // для хранения 16 битов используем unsigned int unsigned int bitsToSend[3] = {0, 0, 0}; // выключаем светодиоды на время передачи битов digitalWrite(latchPin, LOW); // устанавливаем HIGH в соответствующий бит bitWrite(bitsToSend[whichPin / 8], whichPin % 8, whichState); for (int i = 0; i < 3; i++) shiftOut(dataPin, clockPin, MSBFIRST, bitsToSend[i]); // "защелкиваем" регистр, чтобы биты появились на выходах регистра digitalWrite(latchPin, HIGH); } void loop() { // получаем данные от клиента: EthernetClient client = server.available(); if (client) { // HHTP запрос оканчивается пустой строкой boolean currentLineIsBlank = true; while (client.connected()) { if (client.available()) { char c = client.read(); // если вы дошли до конца строки и следующая строка пустая, // http запрос заканчивается и можно вывести ответ //считывает строку URL от $ до первого пробела if (incoming && c == ' ') { incoming = 0; } if (c == '$') { incoming = 1; } // проверка строки URL. В ней присутствует $1 или $2 if (incoming == 1) { Serial.println(c); if (c == '1') { Serial.println("1.2"); registerWrite(1, HIGH); registerWrite(5, HIGH); } if (c == '2') { Serial.println("6.8"); registerWrite(6, HIGH); registerWrite(8, HIGH); } } if (c == '\n') { // начинаем новую строку currentLineIsBlank = true; } else if (c != '\r') { // получаем символ на текущей строке currentLineIsBlank = false; } } } // даем веб-браузеру время для получения данных delay(1); // закрываем соединение: client.stop(); } }"На сдвиговый регистр Вы всегда передаёте только в режиме master, т.к. именно Вы иницируете передачу. а не сдвиговый регистр - ему-то это зачем?"
можете дать более подробное объяснение?
Ну, если просто ... представьте - двое общаются. Один начинает общение когда ему удобно. А другой - просто ждёт пока к нему обратятся и может ждать бесконечно. Мастер - это тот, кто начинает общение и заканчивает его, а слейв - делает что ему скажут - принимает оосбщения от мастера, выдаёт свои и т.п.
Перед началом общения слейв просто сидит и ждёт пока мастер к нему обратится. Мастер же как раз обращается - начинает беседу.
С этой точки зрения любой сервер - слейв, а клиент - мастер.
В случае с регистром, кто начинает общение, микропроцессор или регистр? КОнечно, микропроцессор - значит он в режиме мастер.