Podłączenie:
W tym przypadku wykorzystałem gotową nakładkę na Arduino Nano, która pozwala w bardzo łatwy sposób podłączyć ze sobą te układy.Poniżej podstawowy opis podłączenia:
- Pin SS (CS) - D10
- Pin MOSI (SI) - D11
- Pin MISO (SO) - D12
- Pin SCK - D13
Dodatkowo należy podłączyć zasilanie do 5V oraz GND. W przykładach wykorzystuje bibliotekę UIPEthernet, która domyślnie posiada przyporządkowanie pinów takie jak powyżej.
Przykłady autora biblioteki:
W celu sprawdzenia działania można wykorzystać przykłady udostępnione przez autora biblioteki. Poniżej zmodyfikowane wersje dla TCP Client oraz TCP Server:
TCP Klient:
- #include <UIPEthernet.h>
- #include "utility/logging.h"
- #define MACADDRESS 0x48,0x53,0x4B,0x03,0x55,0x05
- #define MYIPADDR 169,254,24,158
- #define MYIPMASK 255,255,255,0
- #define MYDNS 192,168,1,1
- #define MYGW 169,254,24,20
- #define LISTENPORT 1000
- EthernetClient client;
- unsigned long next;
- void PrintNetworkSettings()
- {
- Serial.print("localIP: ");
- Serial.println(Ethernet.localIP());
- Serial.print("subnetMask: ");
- Serial.println(Ethernet.subnetMask());
- Serial.print("gatewayIP: ");
- Serial.println(Ethernet.gatewayIP());
- Serial.print("dnsServerIP: ");
- Serial.println(Ethernet.dnsServerIP());
- }
- void setup() {
- Serial.begin(115200);
- Serial.print("Client start: ");
- uint8_t mac[6] = {0x00,0x01,0x02,0x03,0x04,0x05};
- Ethernet.begin(mac); //Configure IP address via DHCP
- //Ethernet.begin(mac,myIP,myDNS,myGW,myMASK); //Without DHCP
- PrintNetworkSettings();
- }
- void loop() {
- if (((signed long)(millis() - next)) > 0)
- {
- next = millis() + 5000;
- // replace hostname with name of machine running tcpserver.pl
- // if (client.connect("server.local",5000))
- if (client.connect(IPAddress(192,168,0,1),1000))
- {
- client.println(F("DATA from Client"));
- int size;
- while ((client.available()==0) && (millis()<next)) { }
- while((size = client.available()) > 0)
- {
- uint8_t* msg = (uint8_t*)malloc(size+1);
- memset(msg, 0, size+1);
- size = client.read(msg,size);
- free(msg);
- }
- //disconnect client
- client.stop();
- }
- else
- {
- }
- }
- }
TCP Server:
- #define MACADDRESS 0x00,0x01,0x02,0x03,0x04,0x05
- #define MYIPADDR 192,168,1,6
- #define MYIPMASK 255,255,255,0
- #define MYDNS 192,168,1,1
- #define MYGW 192,168,1,1
- #define LISTENPORT 1000
- #define UARTBAUD 115200
- #include <UIPEthernet.h>
- #include "utility/logging.h"
- EthernetServer server = EthernetServer(LISTENPORT);
- void PrintNetworkSettings()
- {
- Serial.print("localIP: ");
- Serial.println(Ethernet.localIP());
- Serial.print("subnetMask: ");
- Serial.println(Ethernet.subnetMask());
- Serial.print("gatewayIP: ");
- Serial.println(Ethernet.gatewayIP());
- Serial.print("dnsServerIP: ");
- Serial.println(Ethernet.dnsServerIP());
- }
- void setup() {
- Serial.begin(UARTBAUD);
- Serial.println("Start Server");
- uint8_t mac[6] = {MACADDRESS};
- /*
- uint8_t myIP[4] = {MYIPADDR};
- uint8_t myMASK[4] = {MYIPMASK};
- uint8_t myDNS[4] = {MYDNS};
- uint8_t myGW[4] = {MYGW};
- Ethernet.begin(mac,myIP,myDNS,myGW,myMASK);
- */
- Ethernet.begin(mac); //DHCP
- PrintNetworkSettings();
- server.begin();
- }
- void loop() {
- size_t size;
- if (EthernetClient client = server.available())
- {
- while((size = client.available()) > 0)
- {
- uint8_t* msg = (uint8_t*)malloc(size+1);
- memset(msg, 0, size+1);
- size = client.read(msg,size);
- free(msg);
- }
- client.stop();
- }
- }
Oby przypadki można zweryfikować pojedynczo np. przez użycie programu hercules.
Wersja pierwsza:
Po wciśnięciu przycisku klient lub serwer wysyłają informację o wciśnięciu przycisku. W zależności od tego gdzie dany przycisk został wciśnięty.
TCP Server:
- #include <UIPEthernet.h>
- //---------------------------------------
- /* Define protocol frame */
- #define START_ACK 0x01
- #define CONTOL_IN_OUT_FRAME 0x23
- #define KEEP_ALIVE_FRAME 0x45
- //-------------------------------------
- #define IN_1 2
- #define IN_2 3
- #define IN_3 4
- #define IN_4 5
- #define OUT_1 6
- #define OUT_2 7
- #define OUT_3 8
- #define OUT_4 9
- #define OUT_STATUS_DIODE 15
- //----------------------------------------
- #define MACADDRESS 0x48,0x53,0x4B,0x03,0x55,0x05
- #define MYIPADDR 169,254,24,158
- #define MYIPMASK 255,255,255,0
- #define MYDNS 192,168,1,1
- #define MYGW 169,254,24,20
- #define LISTENPORT 1000
- #define UARTBAUD 115200
- //----------------------------------------
- EthernetServer server = EthernetServer(LISTENPORT);
- uint16_t countConnection = 0;
- uint8_t sendFlag = 0;
- unsigned long time_now;
- int buttonPrevState1 = 0;
- int buttonPrevState2 = 0;
- int buttonPrevState3 = 0;
- int buttonPrevState4 = 0;
- void CheckBtnMonostable(int * buttonPrevState, int buttonState, uint8_t pinNumber)
- {
- if (buttonState == LOW && *buttonPrevState == 0)
- {
- *buttonPrevState = 1;
- Serial.print("Wcisniety: ");
- Serial.println(pinNumber, DEC);
- uint8_t buf[5] = {0x01, 0x02, 0x34, pinNumber, 0x01};
- int val = server.write(buf, 5);
- }
- else if (buttonState == HIGH && *buttonPrevState == 1)
- {
- *buttonPrevState = 0;
- Serial.print("Puszczony: ");
- Serial.println(pinNumber, DEC);
- uint8_t buf[5] = {0x01, 0x02, 0x34, pinNumber, 0x00};
- int val = server.write(buf, 5);
- }
- }
- void InitGpio(uint8_t gpioInOut)
- {
- if(gpioInOut == 0) //Input
- {
- pinMode(IN_1, INPUT_PULLUP);
- pinMode(IN_2, INPUT_PULLUP);
- pinMode(IN_3, INPUT_PULLUP);
- pinMode(IN_4, INPUT_PULLUP);
- }
- else if(gpioInOut == 1) //Output
- {
- pinMode(OUT_1, OUTPUT);
- pinMode(OUT_2, OUTPUT);
- pinMode(OUT_3, OUTPUT);
- pinMode(OUT_4, OUTPUT);
- digitalWrite(OUT_1, LOW);
- digitalWrite(OUT_2, LOW);
- digitalWrite(OUT_3, LOW);
- digitalWrite(OUT_4, LOW);
- }
- }
- void InitDiodeStatusGpio(void)
- {
- pinMode(OUT_STATUS_DIODE, OUTPUT);
- digitalWrite(OUT_STATUS_DIODE, LOW);
- }
- void SetPinStatus(uint8_t pinNumber, uint8_t pinState)
- {
- /*
- msg[3] pin number from 1 to 4
- msg[4] pin state 0 is LOW, 1 is HIGH
- */
- digitalWrite((pinNumber + 5), pinState);
- }
- void PrintNetworkSettings()
- {
- Serial.print("localIP: ");
- Serial.println(Ethernet.localIP());
- Serial.print("subnetMask: ");
- Serial.println(Ethernet.subnetMask());
- Serial.print("gatewayIP: ");
- Serial.println(Ethernet.gatewayIP());
- Serial.print("dnsServerIP: ");
- Serial.println(Ethernet.dnsServerIP());
- }
- void setup() {
- uint8_t mac[6] = {MACADDRESS};
- uint8_t myIP[4] = {MYIPADDR};
- uint8_t myMASK[4] = {MYIPMASK};
- uint8_t myDNS[4] = {MYDNS};
- uint8_t myGW[4] = {MYGW};
- //------------------------------------
- Serial.begin(115200);
- Serial.println("Start");
- //------------------------------------
- InitGpio(0);
- InitGpio(1);
- InitDiodeStatusGpio();
- //------------------------------------
- Ethernet.begin(mac);
- Serial.println("Ethernet.begin");
- //Ethernet.begin(mac,myIP,myDNS,myGW,myMASK);
- //Serial.println( "ServerBegin");
- PrintNetworkSettings();
- server.begin();
- }
- void loop()
- {
- int buttonState1 = digitalRead(IN_1);
- int buttonState2 = digitalRead(IN_2);
- int buttonState3 = digitalRead(IN_3);
- int buttonState4 = digitalRead(IN_4);
- CheckBtnMonostable(&buttonPrevState1, buttonState1, 1);
- CheckBtnMonostable(&buttonPrevState2, buttonState2, 2);
- CheckBtnMonostable(&buttonPrevState3, buttonState3, 3);
- CheckBtnMonostable(&buttonPrevState4, buttonState4, 4);
- size_t size;
- EthernetClient client = server.available();
- if(client)
- {
- digitalWrite(OUT_STATUS_DIODE, HIGH);
- time_now = millis();
- countConnection = 0;
- sendFlag = 0;
- while((size = client.available()) > 0)
- {
- uint8_t* msg = (uint8_t*)malloc(size+1);
- memset(msg, 0, size+1);
- size = client.read(msg,size);
- if(msg[0] == START_ACK) /* Sprawdź czy bit startu*/
- {
- if(msg[2] == CONTOL_IN_OUT_FRAME) /* Ramka zmiany stanu wejscia wyjscia*/
- {
- if(msg[1] == 0x02)
- {
- SetPinStatus(msg[3], msg[4]);
- client.write(msg,size);
- }
- }
- else if(msg[2] == KEEP_ALIVE_FRAME)
- {
- countConnection = 0;
- sendFlag = 0;
- digitalWrite(OUT_STATUS_DIODE, HIGH);
- }
- }
- else { client.write("Undefined",9); }
- free(msg);
- }
- }
- //Send Keep Alive Frame if no communication occurs
- if(millis() - time_now > 5000){
- time_now = millis();
- if(sendFlag == 0)
- {
- uint8_t buf[5] = {0x01, 0x02, 0x45};
- int val = server.write(buf, 3);
- sendFlag = 1;
- }
- }
- if(sendFlag == 1 && millis() - time_now > 2000)
- {
- time_now = millis();
- countConnection = 0;
- sendFlag = 0;
- digitalWrite(OUT_STATUS_DIODE, LOW);
- }
- }
TCP Klient:
- #include <UIPEthernet.h>
- //---------------------------------------
- /* Define protocol frame */
- #define START_ACK 0x01
- #define CONTROL_IN_OUT_FRAME 0x23
- #define BTN_SERVER_CLICK 0x34
- #define KEEP_ALIVE_FRAME 0x45
- //---------------------------------------
- /* Define pin numbers */
- #define IN_1 2
- #define IN_2 3
- #define IN_3 4
- #define IN_4 5
- #define OUT_1 6
- #define OUT_2 7
- #define OUT_3 8
- #define OUT_4 9
- #define OUT_SER_1 16
- #define OUT_SER_2 17
- #define OUT_SER_3 18
- #define OUT_SER_4 19
- #define OUT_STATUS_DIODE 15
- //---------------------------------------
- EthernetClient client;
- unsigned long time_now;
- uint16_t keepAliceMillisPeriod = 6000;
- //---------------------------------------
- int buttonPrevState1 = 0;
- int buttonPrevState2 = 0;
- int buttonPrevState3 = 0;
- int buttonPrevState4 = 0;
- //----------------------------------------------------------------
- void CheckBtnMonostable(int * buttonPrevState, int buttonState, uint8_t pinNumber)
- {
- if (buttonState == LOW && *buttonPrevState == 0)
- {
- *buttonPrevState = 1;
- uint8_t buf[5] = {0x01, 0x02, 0x23, pinNumber, 0x01};
- int val = client.write(buf, 5);
- Serial.println(val, DEC);
- }
- else if (buttonState == HIGH && *buttonPrevState == 1)
- {
- *buttonPrevState = 0;
- uint8_t buf[5] = {0x01, 0x02, 0x23, pinNumber, 0x00};
- int val = client.write(buf, 5);
- Serial.println(val, DEC);
- }
- }
- void CheckBtnBistable(int * buttonPrevState, int buttonState, uint8_t pinNumber)
- {
- if (buttonState == LOW)
- {
- *buttonPrevState = 1;
- uint8_t buf[5] = {0x01, 0x02, 0x23, pinNumber, 0x01};
- int val = client.write(buf, 5);
- Serial.println(val, DEC);
- }
- }
- void SetPinStatus(uint8_t pinNumber, uint8_t pinState)
- {
- /*
- msg[3] pin number from 1 to 4
- msg[4] pin state 0 is LOW, 1 is HIGH
- */
- digitalWrite((pinNumber + 5), pinState);
- }
- void DefineInputOutput_SetDefaultState(void)
- {
- pinMode(IN_1, INPUT_PULLUP);
- pinMode(IN_2, INPUT_PULLUP);
- pinMode(IN_3, INPUT_PULLUP);
- pinMode(IN_4, INPUT_PULLUP);
- pinMode(OUT_1, OUTPUT);
- pinMode(OUT_2, OUTPUT);
- pinMode(OUT_3, OUTPUT);
- pinMode(OUT_4, OUTPUT);
- digitalWrite(OUT_1, LOW);
- digitalWrite(OUT_2, LOW);
- digitalWrite(OUT_3, LOW);
- digitalWrite(OUT_4, LOW);
- pinMode(OUT_SER_1, OUTPUT);
- pinMode(OUT_SER_2, OUTPUT);
- pinMode(OUT_SER_3, OUTPUT);
- pinMode(OUT_SER_4, OUTPUT);
- digitalWrite(OUT_SER_1, HIGH);
- digitalWrite(OUT_SER_2, HIGH);
- digitalWrite(OUT_SER_3, HIGH);
- digitalWrite(OUT_SER_4, HIGH);
- pinMode(OUT_STATUS_DIODE, OUTPUT);
- digitalWrite(OUT_STATUS_DIODE, LOW);
- }
- //----------------------------------------------------------------
- void setup()
- {
- uint8_t mac[6] = {0x00,0x01,0x02,0x03,0x04,0x05};
- Serial.begin(115200);
- Serial.println("Client start");
- DefineInputOutput_SetDefaultState();
- Ethernet.begin(mac); //Configure IP address via DHCP
- }
- void loop() {
- //-------------------------------------------
- int buttonState1 = digitalRead(IN_1);
- int buttonState2 = digitalRead(IN_2);
- int buttonState3 = digitalRead(IN_3);
- int buttonState4 = digitalRead(IN_4);
- //-------------------------------------------
- if(!client.connected())
- {
- Serial.println("123");
- digitalWrite(OUT_STATUS_DIODE, LOW);
- client.connect(IPAddress(150,153,100,92),1000);
- }
- if (client.connected())
- {
- CheckBtnMonostable(&buttonPrevState1, buttonState1, 1);
- CheckBtnMonostable(&buttonPrevState2, buttonState2, 2);
- CheckBtnMonostable(&buttonPrevState3, buttonState3, 3);
- CheckBtnMonostable(&buttonPrevState4, buttonState4, 4);
- int size;
- while((size = client.available()) > 0) {
- uint8_t* msg = (uint8_t*)malloc(size+1);
- memset(msg, 0, size+1);
- size = client.read(msg,size);
- time_now = millis();
- if(msg[0] == START_ACK) /* Sprawdź czy bit startu*/
- {
- if(msg[2] == CONTROL_IN_OUT_FRAME) /* Ramka zmiany stanu wejscia wyjscia*/
- {
- if(msg[1] == 0x02)
- {
- Serial.println("Client zmiana");
- SetPinStatus(msg[3], msg[4]);
- digitalWrite(OUT_STATUS_DIODE, HIGH);
- }
- }
- else if(msg[2] == BTN_SERVER_CLICK)
- {
- digitalWrite((msg[3] + 15), !msg[4]);
- }
- else if(msg[2] == KEEP_ALIVE_FRAME)
- {
- uint8_t buf[5] = {0x01, 0x02, 0x45};
- client.write(buf, 3);
- time_now = millis();
- digitalWrite(OUT_STATUS_DIODE, HIGH);
- }
- }
- else {
- Serial.println("Unknown frame");
- }
- free(msg);
- }
- }
- else { }
- if(millis() - time_now > keepAliceMillisPeriod){
- time_now = millis();
- digitalWrite(OUT_STATUS_DIODE, LOW);
- client.stop();
- Serial.println("Con active");
- }
- }
Wersja druga:
W tym przykładzie serwer odpytuje dwóch klientów o stan przycisków jak i o stan wyjść. Reakcja nie jest tak szybka jak w przypadku pierwszego przykładu. Natomiast zapewniona jest większa niezawodność przez ciągłą kontrolę i sprawdzanie stanu wejść oraz wyjść.
Serwer wysyła informację najpierw do jednego a potem do drugiego klienta aby wykonał akcję np. otwarcie drzwi itp itd. Po przesłaniu zapytania do pierwszego urządzenia wysyła taką samą informację do drugiego. Gdy on również nie wykona żadnej akcji to następuje ponowne zaalarmowanie klienta 1.
Konfiguracja dla obu programów jest zapisana w wewnętrznej pamięci EEPROM. Dzięki temu po wysłaniu zmiany do programu, za pomocą odpowiedniej ramki, można układ dowolnie konfigurować.
Programy z tej części posta można pobrać z dysku Google pod tym linkiem. Głównym powodem jest ich dosyć duża objętość, która utrudnia umieszczenie ich bezpośrednio w poście.
Konfiguracja dla obu programów jest zapisana w wewnętrznej pamięci EEPROM. Dzięki temu po wysłaniu zmiany do programu, za pomocą odpowiedniej ramki, można układ dowolnie konfigurować.
Programy z tej części posta można pobrać z dysku Google pod tym linkiem. Głównym powodem jest ich dosyć duża objętość, która utrudnia umieszczenie ich bezpośrednio w poście.