how to acquire arduino ethercard udp receive data? - arduino

I have a problem in accessing received udp string, I can get it by serial though. I just need to get my incoming udp data into a variable using the ethercard library in loop() function so I can use them in my program.Here's the code I'm working with:
#include <EtherCard.h>
#include <IPAddress.h>
#define STATIC 1 // set to 1 to disable DHCP (adjust myip/gwip values below)
#if STATIC
// ethernet interface ip address
static byte myip[] = { 192,168,1,200 };
// gateway ip address
static byte gwip[] = { 192,168,1,1 };
#endif
// ethernet mac address - must be unique on your network
static byte mymac[] = { 0x70,0x69,0x69,0x2D,0x30,0x31 };
byte Ethernet::buffer[500]; // tcp/ip send and receive buffer
//callback that prints received packets to the serial port
void udpSerialPrint(word port, byte ip[4], const char *data, word len) {
Serial.println(data);
}
void setup(){
Serial.begin(57600);
Serial.println("\n[backSoon]");
if (ether.begin(sizeof Ethernet::buffer, mymac, 10) == 0)
Serial.println( "Failed to access Ethernet controller");
#if STATIC
ether.staticSetup(myip, gwip);
#else
if (!ether.dhcpSetup())
Serial.println("DHCP failed");
#endif
ether.printIp("IP: ", ether.myip);
ether.printIp("GW: ", ether.gwip);
ether.printIp("DNS: ", ether.dnsip);
//register udpSerialPrint() to port 1337
ether.udpServerListenOnPort(&udpSerialPrint, 1337);
//register udpSerialPrint() to port 42.
ether.udpServerListenOnPort(&udpSerialPrint, 42);
}
void loop(){
//this must be called for ethercard functions to work.
ether.packetLoop(ether.packetReceive());
//? incoming = data; <--- this is my problem
//Serial.println(incoming);
}
It's just a slightly modified version of the UDPListener example that comes with the ethercard library.
Thank you

I'm still on a steep learning curve myself but have managed to get UDP talking between units so hope following helps. Suspect the quickest way would be to create a global variable such as:
char gUDPdata[30] = "";
then in your udpSerialPrint routine add the following for a quick and dirty result. This copies 'data' to a global variable that you can see in your main loop.
Serial.println(data);
data[0] = 0;
strcpy(data, gUDPdata);
then in your main loop following should produce same as Serial.print in the udpSerialPrint routine.
Serial.println(gUDPdata);

Related

Broadcasting messages via UDP over esp8266

I am connecting 4 nodemcu (esp8266). 1 esp8266 is used as access point and others are connected to it.
When I send UDP packets as a broadcast message to all the esp8266 via with esp8266 as access point it is not recieved by the others however when I use a home router or even by mobile hotspot as access point, the broadcast messages are received by the other esp8266.
Also, I have posted here a part of my code that is used for UDP so there may be some variables that you will see as undeclared but they are originally declared and the code is working when I connect it with Access Point that is not esp8266
Code For Access Point:
#include
void setup()
{
Serial.begin(115200);
Serial.println();
Serial.print("Setting soft-AP ... ");
boolean result = WiFi.softAP("ssid", "password123456");
if(result == true)
{
Serial.println("Ready");
}
else
{
Serial.println("Failed!");
}
}
void loop()
{
Serial.printf("Stations connected = %d\n",
WiFi.softAPgetStationNum());
delay(3000);
}
Code for sending UPD packet as broadcast:
unsigned int localPort = 2000;
IPAddress SendIP(192,168,43,255);
setup()
{
udp.begin(localPort);
Serial.print("Local port: ");
Serial.println(udp.localPort());
}
loop()
{
udp.beginPacket(SendIP, 2000);
udp.write("p");
udp.endPacket();
}
Code for Recieving UDP packets:
void loop()
{
int packetSize = udp.parsePacket();
if(packetSize)
{
udp.read(packetBuffer,UDP_TX_PACKET_MAX_SIZE);
p = packetBuffer[0];
Serial.println(p);
function();
}
Please tell me whats the problem with using esp8266 as access point to send UDP packets.
And if esp8266 can not be used please tell me any other chip that can do the work, I want to make a portable system so I cannot use the router.
The default IP address of ESP8266 router in AP mode is 192.168.244.1.
Try to change sending address to 192.168.244.255.

Arduino LORA Send and Receive Data

I tried to allow sending and receiving data using 2 Arduino Unos, 2 LORA chips (SX1278 433MHz), 2 antennas and 2 Arduino IDE.
Problem is with the receiving data command.
This is the code for SENDING command:
#include <SPI.h>
#include <LoRa.h>
int counter = 0;
const int ss = 10;
const int reset = 9;
const int dio0 = 2;
void setup() {
Serial.begin(9600);
LoRa.begin(433E6);
LoRa.setPins(ss, reset, dio0);
while (!Serial);
Serial.println("LoRa Sender");
}
void loop() {
Serial.print("Sending packet: ");
Serial.println(counter);
// send packet
LoRa.beginPacket();
LoRa.print("hello ");
LoRa.print(counter);
LoRa.endPacket();
counter++;
delay(5000);
}
On serial monitor, I succeed in sending packages, but not receiving. This is the RECEIVING code:
#include <SPI.h>
#include <LoRa.h>
const int ss = 10;
const int reset = 9;
const int dio0 = 2;
void setup() {
Serial.begin(9600);
LoRa.begin(433E6);
LoRa.setPins(ss, reset, dio0);
while (!Serial);
Serial.println("LoRa Receiver");
}
void loop() {
// try to parse packet
int packetSize = LoRa.parsePacket();
if (packetSize) {
// received a packet
Serial.print("Received packet '");
// read packet
while (LoRa.available()) {
Serial.print((char)LoRa.read());
Serial.print("hello ");
}
// print RSSI of packet
Serial.print("' with RSSI ");
Serial.println(LoRa.packetRssi());
}
}
I used instructions about connections from this git page:
https://github.com/sandeepmistry/arduino-LoRa
To make this board work, I had to explicitly initialize SPI
SPI.begin(/*sck*/ 5, /*miso*/ 19, /*mosi*/ 27, /*ss*/ cs);
It may be the same for yours. Also, you should properly initialize Lora:
while (!LoRa.begin(433E6)) {
Serial.print(".");
delay(500);
}
Serial.println("LoRa Initializing OK!");
With the code you posted, you don't really know if it initialized correcly or if it's actually sending any data.
First I haven't worked with Lora library. I worked with SX1278 libaray. So I can help you with that.
At first here is the link to the libaray - Lora SX1278.h library
Now you might ask why I'm not using the library from the original GitHub repo. Well I faced issue with that library and the issue is this:
The sx1278::getPacket() library function is modified to stabilize the Lora receive functionality. There was a bug which led the esp to panic. The payloadlength read from the REG_FIFO register was not checked for valid value which led to reading the REG_FIFO register read for over 65000 times. Moreover yield() is added in time consuming parts of this function.
That is why I'm using this custom library. Anyway, for you:
You can use this function to send packet:
T_packet_state = sx1278.sendPacketTimeoutACK(ControllerAddress, message); //T_packet_state is 0 if the packet data is sent successful.
Also to receive data use this function:
R_packet_state = sx1278.receivePacketTimeoutACK(); //R_packet_state is 0 if the packet data is received successfully.
And at the beginning of the code just define this few things:
//Lora SX1278:
#define LORA_MODE 10 //Add your suitable mode from the library
#define LORA_CHANNEL CH_6_BW_125 //Ch number and Bandwidth
#define LORA_ADDRESS 3 //Address of the device from which you will send data
uint8_t ControllerAddress = 5; //Address of receiving end device
My first decent answer on StackOverflow. Finger Crossed

Initializing Xbee S1 by an Arduino mini pro

I am trying to configurate my XBee module by an Arduino pro mini that is connected to my computer by de FTDI basic from sparkfun.
I already can write and send data from the Xbee to another Xbee module by the Arduino.
My problem is that I want to configure the Xbee by the arduino. I am sending ‘+++’ with the arduino to my Xbee and want to receive the ‘OK’ from the Xbee with the serial monitor from the arduino editor. The problem is that I can send it but never receive and ‘OK’, and when I am trying to configure the Xbee the configuration never happened. So I cant reach the Xbee command line.
uint8_t pinRx = 0, pinTx = 1; //Initialise pins on the Arduino
char GotChar;
long BaudRate = 4800;
int incomingByte=0;
SoftwareSerial mySerial( pinRx , pinTx ); //Initialise SoftwareSerial
void init_USB()
{
Serial.begin(BaudRate);
Serial.println("Start");
mySerial.begin(BaudRate);
}
void init_XBee()
{
Serial.begin(9600);
int check = 0;
while(T_XBEE_CONTROLLER_CheckOK() == 0)
{
Serial.println("CheckOK");
Serial.write("+++");
delay(2000);
}
Serial.println("ATCH 8\r");
delay(2000);
Serial.write("ATID 1234\r");
delay(2000);
Serial.write("+++");
delay(2000);
Serial.write("ATPL 0\r");
delay(2000);
Serial.write("+++");
delay(2000);
Serial.write("ATAP 2\r");
delay(2000);
}
int T_XBEE_CONTROLLER_CheckOK()
{
char ch[2];
ch[0] = 0x00;
while(! ((ch[0] == 'O' ) && (ch[1] == 'K') ))
{
ch[0] = mySerial.read();
ch[1] = mySerial.read();
if((ch[0] != 'O') && (ch[1] != 'K') && (ch[2] != '\r'))
{
Serial.println("FAILED");
return 0;
}
Serial.println("SUCCES");
return 1;
}
return 0;
}
it is a stupid answer but first of all, you should check that your Xbee is configured as AT device instead of API device. If it is API mode, the module wont understand the messages.
To do that you just have to use X-CTU application and read the configuration of the module, and change it to AT device.
Hope that helps.
Thanks for the response and the help, and also sorry for the late response.
I already solved the problem. The problem was the function write(). If you want to reach the command mode from the XBee you should only send "+++". If there is some kind of character behind the "+++" you can't reach the command line. The function write put a (for me) unknown character behing the "+++". So that's the problem for not reaching the command line.
To resolve this problem just use the function print("+++"). After using this function it is possible to reach the command line.
You have to read from the serial right after you send the +++ command, because this is where the xbee writes 'OK'. Also a better way to respect the guard times is to wait for a reply, and test to see if it is 'OK'.
Here is my code, I don't remember if it was working the last time I checked but I will just paste it here and you can modify it as you like. All it does is broadcast A1, B2, C3, etc.
There's a lot of commenting out where I was experimenting, but the regular comments are informative. Make sure you go through it step by step, it's quite simple when you get your head around it. Don't forget to change the destination address low to 0xFFFF if you want to broadcast.
In the end you'll come to the same realisation I did that AT mode is not suitable for configuring the xbee by writing programs.
For example I had an xbee constantly transmitting the number '2', and when another xbee was entering command mode using this code, it would receive the number 2 from the remote xbee when it should have received the 'OK' message from the local xbee, thus the program didn't acknowledge it being in command mode and breaking. When entering command mode you'd think an xbee would turn it's receiver off, but that's not the case so you can easily get into trouble.
If you want to do it the right way, have a look at API mode. I have series 1 xbee's so I'm implementing the Digimesh protocol, which so far I haven't seen anyone online do, but it's almost identical to the Zigbee so it's easy. If you'd like I can give you my code for that which can serve as a simple example.
/*
unicast_configure
Configure an XBee for unicast transmission and transmit
some characters to test
*/
#include <SoftwareSerial.h>
// Pins on Bees Shield:
SoftwareSerial xbee(2, 3); // TX, RX
boolean configured;
char c = 'A';
boolean configureRadio() {
// Set the data rate for the SoftwareSerial port:
xbee.begin(9600);
// Put the radio in command mode:
Serial.write("Entering command mode\r");
delay(1000);
while(xbee.available()>0) {xbee.read();}
xbee.write("+++");
while(xbee.available()>0) {xbee.read();}
//delay(1000);
//while(xbee.available() > 0) {Serial.write(xbee.read());}
String ok_response = "OK\r"; // The response we expect
// Read the text of the response into the response variable
// This satisfies the guard time by waiting for the OK message
String response = String("");
while (response.length() < ok_response.length()) {
if (xbee.available() > 0) {
response += (char) xbee.read();
}
}
Serial.println("response1: " + response);
// If we got received OK, configure the XBee and return true:
if (response.equals(ok_response)) {
Serial.println("Enter command mode successful");
// Restore to default values:
Serial.println("Restoring default values before making changes");
xbee.write("ATRE\r");
Serial.println("Setting addr high");
xbee.write("ATDH0\r"); // Destination high
//while(xbee.available() > 0) {Serial.write(xbee.read());}
Serial.println("Setting addr low");
xbee.write("ATDL1\r"); // Destination low-REPLACE THIS
//while(xbee.available() > 0) {Serial.write(xbee.read());}
Serial.println("Setting MY address");
xbee.write("ATMYFFFF\r");
// Apply changes:
Serial.println("Applying changes");
xbee.write("ATAC\r");
/*
///////////////////////////////////////////////
// Write to non-volatile memory:
// Use similar technique as above to satisfy guard time
Serial.write("Saving\r");
xbee.write("ATWR\r");
String response2 = String("");
//while (xbee.available() > 0) {Serial.write(xbee.read());}
while (response2.length() < ok_response.length()) {
if (xbee.available() > 0) {
response2 += (char) xbee.read();
}
}
Serial.println("response2: " + response2);
if (response2.equals(ok_response)) {
Serial.println("Save successful");
}
else { Serial.println("Save not successful");
return false;
}
// And reset module:
Serial.println("Resetting");
xbee.write("ATFR\r");
///////////////////////////////////////////////
*/
Serial.write("Exit command mode\r");
xbee.write("ATCN\r"); // Exit command mode
//while(xbee.available() > 0) {Serial.write(xbee.read());}
Serial.write("Finished\r");
return true;
} else {
return false; // This indicates the response was incorrect
}
}
void setup() {
Serial.begin(9600); // Begin serial
configured = configureRadio();
}
void loop() {
// Test transmission:
if (configured) {
xbee.print(c);
Serial.print(c);
c = c + 1;
if (c > 'Z') { c = 'A'; }
}
else {
Serial.println("Not configured (in loop)");
delay(5000);
Serial.println("Retrying configuration");
configured = configureRadio();
}
delay(1500);
}

Arduino DHCP error

I'm testing the Ethernet shield with an Arduino Uno, and I'm getting a DHCP error just using the example sketch.
#include <SPI.h>
#include <Ethernet.h>
byte MACaddress[] = { 0x90, 0xAD, 0xDA, 0x0D, 0x96, 0xFE };
EthernetClient client;
void setup() {
Serial.begin(9600);
while (!Serial) {
;
}
// Start the Ethernet connection:
if (Ethernet.begin(MACaddress) == 0) {
Serial.println("Failed to configure Ethernet using DHCP");
for(;;)
;
}
Serial.print("My IP address: ");
for (byte thisByte = 0; thisByte < 4; thisByte++) {
Serial.print(Ethernet.localIP()[thisByte], DEC);
Serial.print(".");
}
Serial.println();
}
void loop() {
}
I've opened the router administration page, and I can see it gave the Arduino an IP address, associated with the MAC address. I've also tried a static IP address in the code (Ethernet.begin(MACaddress, IPaddress)), but it won't work either.
I can't ping the shield IP address that shows in the router administrator page.
What is wrong with just this simple code?
Everything is out of the box, the Arduino and the shield. I haven't done anything with them, just connected the shield to the Arduino and sent the code. It seems everything is working fine, the LEDs are blinking for both boards.
These loops are useless.. Could you try something like:
#if defined(ARDUINO) && ARDUINO > 18
#include <SPI.h>
#endif
#include <Ethernet.h>
#include <EthernetDHCP.h>
// MAC Address
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
const char* ip_to_str(const uint8_t*);
// Initialize the Ethernet server library
Server server(8080);
void setup()
{
Serial.begin(9600);
Serial.println("Attempting to obtain a DHCP lease...");
// Initiate a DHCP session. The argument is the MAC (hardware) address that
// you want your Ethernet shield to use. This call will block until a DHCP
// lease has been obtained. The request will be periodically resent until
// a lease is granted, but if there is no DHCP server on the network or if
// the server fails to respond, this call will block forever.
// Thus, you can alternatively use polling mode to check whether a DHCP
// lease has been obtained, so that you can react if the server does not
// respond (see the PollingDHCP example).
EthernetDHCP.begin(mac);
// Since we're here, it means that we now have a DHCP lease, so we print
// out some information.
const byte* ipAddr = EthernetDHCP.ipAddress();
const byte* gatewayAddr = EthernetDHCP.gatewayIpAddress();
const byte* dnsAddr = EthernetDHCP.dnsIpAddress();
Serial.println("A DHCP lease has been obtained.");
Serial.print("My IP address is ");
Serial.println(ip_to_str(ipAddr));
Serial.print("Gateway IP address is ");
Serial.println(ip_to_str(gatewayAddr));
Serial.print("DNS IP address is ");
Serial.println(ip_to_str(dnsAddr));
// Start the server
server.begin();
}
void loop()
{
// You should periodically call this method in your loop(): It will allow
// the DHCP library to maintain your DHCP lease, which means that it will
// periodically renew the lease and rebind if the lease cannot be renewed.
// Thus, unless you call this somewhere in your loop, your DHCP lease might
// expire, which you probably do not want :-)
EthernetDHCP.maintain();
// listen for incoming clients
Client client = server.available();
if (client) {
// an http request ends with a blank line
boolean currentLineIsBlank = true;
while (client.connected()) {
if (client.available()) {
char c = client.read();
// if you've gotten to the end of the line (received a newline
// character) and the line is blank, the http request has ended,
// so you can send a reply
if (c == '\n' && currentLineIsBlank) {
// send a standard http response header
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println();
// Some misc. HTML
client.println("<title>Arduino Control Panel</title>");
client.println("<center><h1>Control Panel</h1></center>");
client.println("<p></p>");
// output the value of each analog input pin
for (int analogChannel = 0; analogChannel < 6; analogChannel++) {
client.print("Analog input ");
client.print(analogChannel);
client.print(" is ");
client.print(analogRead(analogChannel));
client.println("<br />");
}
break;
}
if (c == '\n') {
// you're starting a new line
currentLineIsBlank = true;
}
else if (c != '\r') {
// you've gotten a character on the current line
currentLineIsBlank = false;
}
}
}
// give the web browser time to receive the data
delay(1);
// close the connection:
client.stop();
}
}
// Just a utility function to nicely format an IP address.
const char* ip_to_str(const uint8_t* ipAddr)
{
static char buf[16];
sprintf(buf, "%d.%d.%d.%d\0", ipAddr[0], ipAddr[1], ipAddr[2], ipAddr[3]);
return buf;
}
I'm not sure what you mean by "I've also tried a static IP address in the code". If you simply replaced
if (Ethernet.begin(MACaddress) == 0) {
with
if (Ethernet.begin(MACaddress, myIP) == 0) {
the result may be unpredictable, because there is no return value.
Read
EthernetBegin
Returns
The DHCP version of this function, Ethernet.begin(mac), returns an int: 1 on a successful DHCP connection, 0 on failure. The other versions don't return anything.
have you tried one of the examples with fixed IP's?

Get client IP address with Arduino

I have an Arduino Uno with Ethernet Shield as server, and I make requests on the Arduino through the Internet. I use two libraries to do it (Ethernet.h and SPI.h).
I want to check the client IP address, so I accept only HTTP requests from a known IP address (for example, 50.50.50.50) which is the static IP address in my office. How can I get the the client IP address on the Arduino?
have a look at the following, this works for TCP:
http://forum.arduino.cc/index.php?PHPSESSID=jh6t8omt7vrb8nget5c9j5dbk4&/topic,82416.0.html
The following is a quote from the author's post, I am just copying the excellent work:
To make it work, I did the following:
I added the following lines to the end of the EthernetClient.cpp file:
uint8_t *EthernetClient::getRemoteIP(uint8_t remoteIP[])
{
W5100.readSnDIPR(_sock, remoteIP);
return remoteIP;
}
I then added the following line (under the virtual void stop(); line)to the EthernetClient.h file:
uint8_t *getRemoteIP(uint8_t RemoteIP[]);//adds remote ip address
Finally I used the following code in my sketch to access the remote IP:
client.getRemoteIP(rip); // where rip is defined as byte rip[] = {0,0,0,0 };
to display the IP in the serial monitor, I used:
for (int bcount= 0; bcount < 4; bcount++)
{
Serial.print(rip[bcount], DEC);
if (bcount<3) Serial.print(".");
}
I've done this using UDP, hopefully this will help you.
Get UDP.h from Google here: UDP.h
Code:
#include <SPI.h>
#include <Ethernet.h>
#include <Udp.h>
// ***** ETHERNET VARS *****
// MAC address and IP for arduino
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192,168,1,98};
unsigned int localPort = 8888; // local port to listen on
// SenderIP and SenderPort are set when message is received
byte SenderIP[IP_LENGTH]; // holds received packet's originating IP
unsigned int SenderPort; // holds received packet's originating port
// buffer for receiving data
char packetBuffer[UDP_TX_PACKET_MAX_SIZE]; //buffer to hold incoming packet
int packetSize = 0;
void setup()
{
Ethernet.begin(mac,ip); //start Ethernet
Udp.begin(localPort); //start UDP
}
void loop()
{
if(NewPortMessage())
{
// Do stuff, SenderIP is the IP where the UDP message was received from
}
}
boolean NewPortMessage()
{
packetSize = Udp.available();
if(packetSize > 0)
{
packetSize -= 8; //subtract UDP 8-byte header
// read the packet into packetBufffer and get the senders IP addr and port number
Udp.readPacket(packetBuffer,UDP_TX_PACKET_MAX_SIZE, SenderIP, SenderPort);
return true;
}
clearPacketBuffer();
return false;
}
void clearPacketBuffer()
{
for(int i=0; i < packetSize; i++)
packetBuffer[i] = 0;
}
what about changing the approach? you could use SOA and you could make your arduino a web client instead of a web server.......then you could handle all of this restrictions in the web server that host your web service, this web service will be the core of your app, and this way you could call it from any mobile device you want :D
just an idea arduino web servers are not very useful, with this approach you could use the internet instead of using LAN only
good luck with your project

Resources