Arduino Polska Forum

Pełna wersja: Moduł Ethernet SPI i Shield
Aktualnie przeglądasz uproszczoną wersję forum. Kliknij tutaj, by zobaczyć wersję z pełnym formatowaniem.
Stron: 1 2
Witajcie.

Napisałem programik pod moduł ENC28J60 który działa poprawnie.
Program działa na skrypcie thingspeak
i bazujący na bibliotece EtherCard.h
Kod:
// Simple demo for feeding some random data to Pachube.
// 2011-07-08 <jc@wippler.nl>
//
// License: GPLv2

// Handle returning code and reset ethernet module if needed
// 2013-10-22 hneiraf@gmail.com

// Modifing so that it works on my setup for www.thingspeak.com.
// Arduino pro-mini 5V/16MHz, ETH modul on SPI with CS on pin 10.
// Also added a few changes found on various forums. Do not know what the
// res variable is for, tweaked it so it works faster for my application
// 2015-11-09 dani.lomajhenic@gmail.com

#include <EtherCard.h>

...
Natomiast żeby nie było za dużo kabli zakupiłem ethernet shield i niestety nie działa na tej bibliotece.
Mimo ze też działa na SPI to cały czas mam komunikat że brak połączenia z serwerem.

Natomiast ten Ethernet Shield działa na wbudowanej bibliotece
<Ethernet.h

Dlaczego moduł https://botland.com.pl/pl/produkty-wycof...crosd.html
nie działa z biblioteką EtherCard.h 

Co trzeba zmienić żeby to odpaliło.

Piny SPI sa dokładnie takie same. CS też jest na 10 - nawet ręcznie próbowałem ustawić CS na 10 też nie odpala.

Problem w tym, że już sporo napisałem kodu i nie tak prosto podmienić tą bibliotekę.
Przykładowy kod działający a Thingspeak na shieldzie.

Kod:
#include <Timers_akcja.h>
#include <SPI.h>
#include <Ethernet.h>


int pin = 0; // analog pin
float tempc = 0; // temperature variables
int samples[8]; // variables to make a better precision
int maxi = -100,mini = 100; // to start max/min temperature
int i;

Timers_akcja <3> Akcja;

// Local Network Settings
byte mac[]     = { 0xD4, 0xA8, 0xE2, 0xFE, 0xA0, 0xA1 }; // Must be unique on local network
byte ip[]      = { 172,16,100,198 };                // Must be unique on local network
byte gateway[] = { 172,16,100,1};
byte subnet[]  = { 255, 255, 255, 0 };

// ThingSpeak Settings
char thingSpeakAddress[] = "api.thingspeak.com";
String writeAPIKey = "A6D0VZ91IT6URB0L";    // Write API Key for a ThingSpeak Channel
const int updateInterval = 10000;        // Time interval in milliseconds to update ThingSpeak  
String analogPin0;

// Variable Setup
long lastConnectionTime = 0;
boolean lastConnected = false;
int failedCounter = 0;
int led1 = 13;

// Initialize Arduino Ethernet Client
EthernetClient client;

void setup()
{

 Serial.begin(57600);
 Ethernet.begin(mac, ip, gateway, subnet);
 delay(1000);
 Serial.print("ETHERNET SHIELD ip  is     : ");
 Serial.println(Ethernet.localIP());
  // Start Ethernet on Arduino
 startEthernet();

Akcja.attach (0, 10000, update_thingspeak);
}
void loop()
{
 Akcja.process(); //włączenie timerów
 //  tempc = ( 5.0 * analogRead(pin) * 100.0) / 1024.0;
 tempc = ( 5.0 * analogRead(pin)) / 1024.0;

 analogPin0 = String(tempc);
 //Serial.println(analogPin0);
 // Print Update Response to Serial Monitor
 if (client.available())
 {
   char c = client.read();
   Serial.print(c);
 }
 
 // Disconnect from ThingSpeak
 if (!client.connected() && lastConnected)
 {
   Serial.println();
   Serial.println("...disconnected.");
   Serial.println();
   
   client.stop();
 }
 
 // Update ThingSpeak
 if(!client.connected() && (millis() - lastConnectionTime > updateInterval))
 {
   updateThingSpeak("field1="+analogPin0);
 }
 
 lastConnected = client.connected();
}

//============================================= MOJE FUNKCJE =================================================================

void updateThingSpeak(String tsData)
{
 if (client.connect(thingSpeakAddress, 80))
 {
   client.print("POST /update HTTP/1.1\n");
   client.print("Host: api.thingspeak.com\n");
   client.print("Connection: close\n");
   client.print("X-THINGSPEAKAPIKEY: "+writeAPIKey+"\n");
   client.print("Content-Type: application/x-www-form-urlencoded\n");
   client.print("Content-Length: ");
   client.print(tsData.length());
   client.print("\n\n");

   client.print(tsData);
   
   lastConnectionTime = millis();
   
   if (client.connected())
   {
     Serial.println("Connecting to ThingSpeak...");
     Serial.println();
     
     failedCounter = 0;
   }
   else
   {
     failedCounter++;
 
     Serial.println("Connection to ThingSpeak failed ("+String(failedCounter, DEC)+")");  
     Serial.println();
   }
   
 }
 else
 {
   failedCounter++;
   
   Serial.println("Connection to ThingSpeak Failed ("+String(failedCounter, DEC)+")");  
   Serial.println();
   
   lastConnectionTime = millis();
 }
}

void startEthernet()
{
 
 client.stop();

 Serial.println("Connecting Arduino to network...");
 Serial.println();  

 delay(1000);
 
 // Connect to network amd obtain an IP address using DHCP
 if (Ethernet.begin(mac) == 0)
 {
   Serial.println("DHCP Failed, reset Arduino to try again");
   Serial.println();
 }
 else {
   Serial.println("Arduino connected to network using DHCP");
   Serial.println();
   Serial.println("Data being uploaded to THINGSPEAK Server.......");
   Serial.println();
 }
 
 delay(1000);
}


void update_thingspeak()
{
updateThingSpeak("field4="+analogPin0);
}
Nic nie szkodzi, napisz jeszcze raz, może tym razem ze zrozumieniem. Dla shielda nie podajesz pinów bo ich się nie zmienia. Wgraj przykładowy szkic i sprawdź czy jest sprawny - jakiś serwer np. Przy okazji zobaczysz co jest niezbędne do wystartowania w sieci, jest tu "Ethernet.begin(mac, ip);", no u Ciebie jeszcze brama, itp. , ale po co znowu to robisz w funkcji startEthernet()? Startujesz na stałym IP, potem chcesz na DHCP?
W swoim kodzie masz obliczanie interwałów czasu wysłania przez millis i jednocześnie przypisanie akacji wg biblioteki Timers_akcja (nie mam jej i nie sprawdzę u siebie, ale to bez sensu).
Jak wejdziesz na thinkspeak to tam też są przykłady jak ma wyglądać kod.
Po prostu otwórz sobie przykład klienta i tylko dodaj thinkspeak, w sumie thinkspeak to może być jedna funkcja, ja używam wersji z GET zamiast POST.
I zmień sobie klucz writeAPIKey po tej publikacji, takie zmienne lepiej dołączać z osobnego pliku, np. hasla.h, wgrywasz do tego samego katalogu jak używany szkic, inkludujesz jak plik biblioteki i nie musisz klepać za każdym razem (ani zdradzać).
Ten przykład co podałem to jest wzięty z sieci.
Moduły oba są sprawne i oba na tym samym chipsecie ENC28J60. Jednego jak podłączam i podpinam bibliotekę jedną to działa a z drugą nie. Z drugim jest na odwrót - na pierwszej bibliotece nie działa a na drugiej działa.
Piny są dokładnie te same zarówno w bibliotece pierwszej jak i drugiej .
Arduino UNO
//   SCK - Pin 13
//   SO  - Pin 12
//   SI  - Pin 11
//   CS  - Pin  10
Dlaczego to nie działa zamiennie - nie wiem, ale próbuję dojść do tego.
Też się dziwię po co jest przypisanie IP i jednocześnie z DHCP - tak był zrobiony przykład - może po to że jak DHCP nie zadziała to weźmie ustawienia te przypisane.

Ta biblioteka timer_akcja jest wyłączona - robiłem tylko próby na niej. - powinno być zakomentowane wywołanie.

Przeglądałem pliki biblioteki ethernet i ethercard i próbuje dojść do ładu z nimi czym się różnią i dlaczego to nie działa

Interesuje mnie żeby działało z Shieldem bo docelowo na nim chcę pozostać

Błąd się pojawia przy inicjalizacji

Kod:
  if (ether.begin(sizeof Ethernet::buffer, mymac, SS) == 0){
    Serial.println( "Failed to access Ethernet controller");
    continue;
  }


Czyli nie ma odpowiedzi z Shielda bo na terminalu cały czas mam komunikat
Failed to access Ethernet controller

Funkcja wygląda tak

Kod:
uint8_t EtherCard::begin (const uint16_t size,
                        const uint8_t* macaddr,
                        uint8_t csPin) {
  using_dhcp = false;
#if ETHERCARD_STASH
  Stash::initMap();
#endif
  copyMac(mymac, macaddr);
  return initialize(size, mymac, csPin);
}


ETHERCARD_STASH jest ustawiony na 1.
No oba nie są na tym samym chipie, z linku jest 5100, nie ma go bo teraz jest pewnie 5500, ale działa tak samo. Do ENC28J60 używałeś przykładów z biblioteki Ethercard, do WS5100 używasz z Ethernet.
Otworzyłem przykład WebClient z Ethernet, wgrałem i działa od strzału (DHCP, przyznany IP jest drukowany na Serial). Próbowałeś od tego zacząć? Zamieniłem serwer google na thinkspeak, wgrałem używane funkcje z ESP, zamieniłem tylko obiekt klienta z WIFI na Ethernet i dalej działa. Zacznij od początku, po co definiujesz SS skoro może działać na domyślnym ustawieniu. Przypuszczam, że lepiłeś to tygodniami i teraz żal, ale przeróbki mogą trwać dłużej, do wykorzystania jest tylko ta część z thinkspeak.
(06-03-2019, 18:54)kaczakat napisał(a): [ -> ]No oba nie są na tym samym chipie, z linku jest 5100, nie ma go bo teraz jest pewnie 5500, ale działa tak samo. Do ENC28J60 używałeś przykładów z biblioteki Ethercard, do WS5100 używasz z Ethernet.
Otworzyłem przykład WebClient  z Ethernet, wgrałem i działa od strzału (DHCP, przyznany IP jest drukowany na Serial). Próbowałeś od tego zacząć? Zamieniłem serwer google na thinkspeak, wgrałem używane funkcje z ESP, zamieniłem tylko obiekt klienta z WIFI na Ethernet i dalej działa. Zacznij od początku, po co definiujesz SS skoro może działać na domyślnym ustawieniu. Przypuszczam, że lepiłeś to tygodniami i teraz żal, ale przeróbki mogą trwać dłużej, do wykorzystania jest tylko ta część z thinkspeak.

OK dziękuję za informacje.

Dlatego tak walczę bo kilka tygodni walczyłem z kodem żeby naprzemiennie wysyłał dane raz na pvmonitor.pl a raz na moją stronę na innym serwerze i zapisywał dane do mysqla
Dodatkowo sprawdza czy ktoś na stronie nie przełączył przycisku i w razie wystąpienia zmiany ma wysterować wyjście przekaźnikowe.
PVmonitor nie daje pełnych statystyk więc tam chcę kontynuować historycznie dane które wysyłam z LanKontrolera, a moja strona ma już robić pełne zestawienia i statystyki plus sterowanie wejściami/wyjściami
na razie strony do testów:
http://www.iwi.gsm.pl/arduino/
http://www.iwi.gsm.pl/arduino2/

Ale wracając do przykładu.
W tym przykładzie z biblioteką ethernet.h wysyła się dane funkcją get
a w ethercard jest jakim post. Dodatkowo jest jakiś PSTR co nie wiadomo co z nim zrobić.
funkcja działająca na starym kontrolerze wyglądała tak:
Kod:
void thingspeak_start(void) {
   int myInt = temperature;  
   char myIntAsString[7];
   itoa(myInt, myIntAsString, 10);

 res = res + 1;

 ether.packetLoop(ether.packetReceive());

 //200 res = 10 seconds (50ms each res)
 if (res == 200) {


   // generate two fake values as payload - by using a separate stash,
   // we can determine the size of the generated message ahead of time
   // field1=(Field 1 Data)&field2=(Field 2 Data)&field3=(Field 3 Data)&field4=(Field 4 Data)&field5=(Field 5 Data)&field6=(Field 6 Data)&field7=(Field 7 Data)&field8=(Field 8 Data)&lat=(Latitude in Decimal Degrees)&long=(Longitude in Decimal Degrees)&elevation=(Elevation in meters)&status=(140 Character Message)
   byte sd = stash.create();
   stash.print("field1=");
   stash.print(myIntAsString);
   stash.print("&field2=");
   stash.print(13);
   stash.print("&field3=");
   stash.print(temperature);
   stash.save();

   //Display data to be sent
   Serial.print("temperatura: ");
   Serial.println(myIntAsString);


   // generate the header with payload - note that the stash size is used,
   // and that a "stash descriptor" is passed in as argument using "$H"
   Stash::prepare(PSTR("POST /update HTTP/1.0" "\r\n"
     "Host: $F" "\r\n"
     "Connection: close" "\r\n"
     "X-THINGSPEAKAPIKEY: $F" "\r\n"
     "Content-Type: application/x-www-form-urlencoded" "\r\n"
     "Content-Length: $D" "\r\n"
     "\r\n"
     "$H"),
   website2, PSTR(APIKEY), stash.size(), sd);
  Serial.println(sd);
   // send the packet - this also releases all stash buffers once done
   session = ether.tcpSend();

// added from: http://jeelabs.net/boards/7/topics/2241
int freeCount = stash.freeCount();
   if (freeCount <= 3) {   Stash::initMap(56); }
 }

  const char* reply = ether.tcpReply(session);

  if (reply != 0) {
    res = 0;
    Serial.println(F(" >>>REPLY recieved...."));
    Serial.println(reply);
  }
  delay(300);

}

Może masz rację że chyba trzeba napisać od nowa bo przerobienie tego nie widzę.
Właśnie dlatego używam GET bo mam lankontroler, on miał możliwość wysyłania danych na thinkspeak tylko tak. I pomimo, że mam już podobne rozwiązania z Arduino to szkoda mi było wyrzucić, a przy okazji działa mi lepiej również na Arduino. Już to wklejałem wiele razy na różne fora, tym razem na bazie ethernet:
Kod:
#include <SPI.h>
#include <Ethernet.h>

uint32_t czasTeraz,czasPoprzedni,tik=10; //tik musi byc mniejszy niz 1000 i dzilic 1000ms na rowne czesci
uint8_t nTik,sekundy,minuty,godziny,dni;
bool fnTik,fsekundy,fminuty,fgodziny,fdni;

const char* serverthink = "api.thingspeak.com";

String apiKey ="";


// Enter a MAC address for your controller below.
// Newer Ethernet shields have a MAC address printed on a sticker on the shield
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };



// Set the static IP address to use if the DHCP fails to assign
IPAddress ip(192, 168, 1, 177);
IPAddress myDns(192, 168, 1, 1);


void setup() {

Serial.begin(115200);
lanStart();

}


void loop()
{
  czas();
  if(fminuty&&(!(minuty%2))) //co dwie minuty
  {
   sendTeperatureTS(nTik,sekundy,minuty,godziny,dni);//po prostu wysylam cokolwiek
  }
 
}




void lanStart()
{
 // start the Ethernet connection:
 Serial.println(F("Initialize Ethernet with DHCP:"));
 if (Ethernet.begin(mac) == 0) {
   Serial.println(F("Failed to configure Ethernet using DHCP"));
   // Check for Ethernet hardware present
   if (Ethernet.hardwareStatus() == EthernetNoHardware) {
     Serial.println(F("Ethernet shield was not found.  Sorry, can't run without hardware. :("));
     while (true) {
       delay(1); // do nothing, no point running without Ethernet hardware
     }
   }
   if (Ethernet.linkStatus() == LinkOFF) {
     Serial.println(F("Ethernet cable is not connected."));
   }
   // try to congifure using IP address instead of DHCP:
   Ethernet.begin(mac, ip, myDns);
 } else {
   Serial.print(F("  DHCP assigned IP "));
   Serial.println(Ethernet.localIP());
 }
 // give the Ethernet shield a second to initialize:
 delay(1000);
 }

void sendTeperatureTS(float tempera1, float tempera2, float tempera3, float tempera4, uint8_t minutki)
{  
// Initialize the Ethernet client library
// with the IP address and port of the server
// that you want to connect to (port 80 is default for HTTP):
EthernetClient client;
 
  if (client.connect(serverthink, 80)) { // use ip 184.106.153.149 or api.thingspeak.com
  Serial.println(F("Polaczono z Thinkspeak "));
  String getStr= F("GET https://api.thingspeak.com/update?api_key=");
   getStr += apiKey;
   getStr += "&field1=";
   getStr += String(tempera1);
   getStr += "&field2=";
   getStr += String(tempera2);
   getStr += "&field3=";
   getStr += String(tempera3);
   getStr += "&field4=";
   getStr += String(tempera4);
   getStr += "&field5=";
   getStr += String(minutki);
   getStr += "\r\n";
  client.print(getStr);
  Serial.println(F("Cos tam probowano wyslac"));
 
  }//end if
 
client.stop();

}//end send

void czas()
{
 czasTeraz=millis();
fnTik=fsekundy=fminuty=fgodziny=fdni=0;
if((uint32_t)(czasTeraz-czasPoprzedni)>=tik)
{
 czasPoprzedni=czasTeraz;
 fnTik=1;
 nTik++;
 if(nTik>=(1000/tik))
 {
   nTik=0;
   sekundy++;
   fsekundy=1;
    if (sekundy>=60)
   {
     sekundy=0;
     minuty++;
     fminuty=1;
     if (minuty>=60)
     {
       minuty=0;
       godziny++;
       fgodziny=1;
       if (godziny>=24)
       {
         godziny=0;
         fdni=1;
         dni++;
   
       }
     }
   }
 }
}
}
Dziękuję.
Wysyłanie super działa, ale z odbieraniem mam problemy.

W moim starym kodzie robiłem to przez callbacka i odbierałem dane do określonego bufora.
W tym przykładzie Ethernet nie jest klasą i nie można zadeklarować Ethernet::buffer[500];
Dałem do funkcji LOOP
if (client.available()) {
char c = client.read();
Serial.print©;
}

i teoretycznie powinno działać ale nie działa. W każdym razie nic nie wypisuje.
Ja to zrobiłem na bazie przykładu ethernet klient z Arduino, pewnie brakuje Ci tej części, którą wykasowałem z loop, bo mi nie było do niczego potrzebne odbieranie. Jak tam zajrzysz to znajdziesz.
no nie do końca.

Jest co prawda takie coś
if (client.available()) {
char c = client.read();
Serial.print©;
}

ale za każdym razem w funkcji dajesz
client.stop();

więc to nie zadziała.

Z drugiej strony jak wejdziemy i zapiszemy to w funcji to odczyta tylko jeden znak. Na razie nie mam pojęcia jak to ugryźć żeby tylko raz na 2 minuty odczytywał bufor a nie ciągle
a nawet jakbym wywalił client.stop to jak to zrobić żeby w LOOP po odczytaniu powiedzmy 100 znaków zrobił client.stop.
Ale jak masz jedną funkcję do klient write, to możesz sobie zrobić analogiczną funkcję do klient read, w parzystych sekundach się uruchamia write, to w nieparzystych odpal read.
Stron: 1 2