Arduino uno + ethernet shield W5100 + 74HC595N в каскаде из 3х

Valeragug
Offline
Зарегистрирован: 31.07.2016

Добрый день.

Недавно начал изучать 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();   }
  }
 } }

Помогите разобраться с этим. В какую сторону копать?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Скетч неполный, так Вы сами себе злобный буратино - не нужна помощь, как хотите.

Рискну предположить, что у Вас оба девайса и W5100, и 74HC595N сидят на SPI и подрались между собой либо за пины, либо за master/slave, либо ещё за что-нибудь. Вот туда и копайте.

Valeragug
Offline
Зарегистрирован: 31.07.2016

Евгений, скетч второй поправлю, он с ошибками, 

А, вам, спасибо за подсказку. Видимо там конфликт в SPI master\SLAVE

Valeragug
Offline
Зарегистрирован: 31.07.2016

Код у меня сейчас такой:

#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? 

a5021
Offline
Зарегистрирован: 07.07.2013

Они оба слейвы на SPI. Чтобы не разбираться, где они конфликтуют, выносите 74HC595N на свободные пины и делайте софтовый SPI, благо протокол простейший -- подняли ногу SCK -> выставили значение очередного бита на ногу MOSI -> опустили ногу SCK -- передача бита состоялась.

Valeragug
Offline
Зарегистрирован: 31.07.2016

Думаю ваш вариант не подойдет.

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

Вообще в идеале нужно открывать файл на удаленном сервере, писать его на SD-карту, а потом уже парся строку из файла подавать биты на различные ножки.

Я понимаю, что задача не тревиальная, но реализовать ее же можно.

a5021
Offline
Зарегистрирован: 07.07.2013

Valeragug пишет:
Думаю ваш вариант не подойдет.

Можно узнать, почему?

Цитата:
У меня основная задача - иметь платформу по подключению большого числа светодиодов, который каждый в отдельности может управляться через POST.

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

Цитата:
Вообще в идеале нужно открывать файл на удаленном сервере, писать его на SD-карту, а потом уже парся строку из файла подавать биты на различные ножки.

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

Цитата:
Я понимаю, что задача не тревиальная, но реализовать ее же можно.

Да не сказал бы я, что такая уж нетривиальная.

MaksMS
Offline
Зарегистрирован: 11.03.2013

Бред какой-то...

М/К и так один поток только обрабатывает, тут в любом случае одновременно работать езернет и 74HC595N  НЕ БУДУТ В ПРИНЦИПЕ. Разделять устройства на разные пины не нужно. Это может только критично, если одно устройство может вызыватся внутри прерывания в момент, когда идет обращение к другому устройству - только в этом случае может быть коллизия. В данном случае в данной задаче этого нет.

Нужно просто правильно выбирать через CS нужное устройство при обращении к нему. 

Valeragug
Offline
Зарегистрирован: 31.07.2016

Что-то я совсем запутался. 

Для работы через аппаратный SPI нужно подключать библиотеку и передавать данные через SPI.transfer()

А для программного SPI, что нужно?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Для чего client описан глобально в строке 6 (блин, вставляйте код правильно - как без номеров обсуждать?), а потом в функции loop он же описан локально. Вы понимаете. что он не глобален? и в loop каждый раз новый создаётся?

На сдвиговый регистр Вы всегда передаёте только в режиме master, т.к. именно Вы иницируете передачу. а не сдвиговый регистр - ему-то это зачем?

Valeragug
Offline
Зарегистрирован: 31.07.2016

Я код перепишу и выложу нормальном виде.

А вот по вашему высказыванию 

"На сдвиговый регистр Вы всегда передаёте только в режиме master, т.к. именно Вы иницируете передачу. а не сдвиговый регистр - ему-то это зачем?"

можете дать более подробное объяснение?

Valeragug
Offline
Зарегистрирован: 31.07.2016

Переписал код основываясь на исходнике из интернета.

#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();

  }
}

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Valeragug пишет:

"На сдвиговый регистр Вы всегда передаёте только в режиме master, т.к. именно Вы иницируете передачу. а не сдвиговый регистр - ему-то это зачем?"

можете дать более подробное объяснение?

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

Перед началом общения слейв просто сидит и ждёт пока мастер к нему обратится. Мастер же как раз обращается - начинает беседу.

С этой точки зрения любой сервер - слейв, а клиент - мастер.

В случае с регистром, кто начинает общение, микропроцессор или регистр? КОнечно, микропроцессор - значит он в режиме мастер.