hello,
i'm working on a project where i need a series of networked arduinos to sequentially take sensor measurements (otherwise the sensors interfere with each other). They're all connected via a network, and use UDP messages to let each other know when its their turn to poll the sensors.
The first arduino in the chain has a timer, so it takes a measurement every 5 seconds and starts the chain:
#include <avr/wdt.h>
#include <SPI.h>
#include <Ethernet.h>
//localClient parameters, for sending data to the server.
byte mac[] = {0x90, 0xA2, 0xDA, 0x0F, 0x05, 0x59};
byte ip[] = {192,168,0,250};
byte nextArduino[] = {192, 168, 0, 251};
EthernetUDP UdpClient;
char packetBuffer[UDP_TX_PACKET_MAX_SIZE];
unsigned int localPort = 8888;
//sonar stuff
int NUM_SONARS = 1;
int sonarPin[] = {2, 3, 4, 5};
int triggerPin = 6;
int sonarThreshold = 12.0;
int sonarState[] = {0, 0, 0, 0};
long pulse;
int numPulses = 3;
int pulseArray[] = {0,0,0,0,0};
int filteredMode = 0;
float current_time;
float last_ping;
boolean debug = true;
void setup() {
if(debug) {
Serial.begin(9600);
}
Ethernet.begin(mac, ip);
if(debug) {
Serial.print("My IP address: ");
Serial.println(Ethernet.localIP());
}
wdt_enable(WDTO_8S);
UdpClient.begin(localPort);
for(int i = 0; i < NUM_SONARS; i++) {
pinMode(sonarPin[i], INPUT);
}
pinMode(triggerPin, OUTPUT);
digitalWrite(triggerPin, LOW);
current_time = 0;
last_ping = 0;
}
void loop() {
wdt_reset();
current_time = millis();
Serial.println("Checking polling server.");
int packetSize = UdpClient.parsePacket();
if (packetSize) {
if(debug) {
Serial.print("Received packet of size ");
Serial.println(packetSize);
Serial.print("From ");
IPAddress remote = UdpClient.remoteIP();
for (int i =0; i < 4; i++) {
Serial.print(remote[i], DEC);
if (i < 3) {
Serial.print(".");
}
}
Serial.print(", port ");
Serial.println(UdpClient.remotePort());
}
}
UdpClient.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE);
if(debug) {
Serial.print("Contents of packet: ");
Serial.println(packetBuffer);
}
if(current_time - last_ping > 5000) {
pingSonars();
}
//fix sensor state for edge detection
//delay(50);
}
String split(String data, char delimiter, int index) {
int found = 0;
int strIndex[] = {0, -1};
int maxIndex = data.length()-1;
for(int i=0; i<=maxIndex && found<=index; i++){
if(data.charAt(i)==delimiter || i==maxIndex){
found++;
strIndex[0] = strIndex[1]+1;
strIndex[1] = (i == maxIndex) ? i+1 : i;
}
}
return found>index ? data.substring(strIndex[0], strIndex[1]) : "";
}
void isort(int *a, int n) {
for (int i = 1; i < n; ++i) {
int j = a[i];
int k;
for (k = i - 1; (k >= 0) && (j < a[k]); k--) {
a[k + 1] = a[k];
}
a[k + 1] = j;
}
}
int mode(int *x,int n){
int i = 0;
int count = 0;
int maxCount = 0;
int mode = 0;
int bimodal;
int prevCount = 0;
while(i<(n-1)){
prevCount=count;
count=0;
while(x[i]==x[i+1]){
count++;
i++;
}
if(count>prevCount&count>maxCount){
mode=x[i];
maxCount=count;
bimodal=0;
}
if(count==0){
i++;
}
if(count==maxCount){//If the dataset has 2 or more modes.
bimodal=1;
}
if(mode==0||bimodal==1){//Return the median if there is no mode.
mode=x[(n/2)];
}
return mode;
}
}
void printArray(int *a, int n) {
for (int i = 0; i < n; i++)
{
Serial.print(a[i], DEC);
Serial.print(' ');
}
Serial.println();
}
void pingSonars() {
digitalWrite(6, HIGH);
for(int i = 0; i < NUM_SONARS; i++) {
for(int j = 0; j < numPulses; j++) {
pulse = pulseIn(sonarPin[i], HIGH);
pulseArray[j] = pulse/147; //convert to inches -- 147 uS per inches
delay(5);
}
isort(pulseArray, numPulses);
filteredMode = mode(pulseArray,numPulses);
//printArray(pulseArray,numPulses);
if(debug) {
Serial.print("Filtered distance for Sonar ");
Serial.print(i);
Serial.print(": ");
Serial.println(filteredMode);
}
if((filteredMode < sonarThreshold) && !sonarState[i]) {
//if we are closer than the threshold and previously were not, this is a rising edge:
if(debug) {
Serial.print("Sonar ");
Serial.print(i);
Serial.println(" triggered!");
}
sonarState[i] = 1;
}
else if (filteredMode > sonarThreshold && sonarState[i]) {
//if we are greater than the threshold and previously were, this is a falling edge:
if(debug) {
Serial.print("Sonar ");
Serial.print(i);
Serial.println(" falling!");
}
sonarState[i] = 0;
}
char message[] = {'G','E','T','\n','S','O','N','A','R','\n','\n'};
UdpClient.beginPacket(nextArduino, localPort);
UdpClient.write(message);
Serial.println("Sent UDP message to next sonar server.");
UdpClient.endPacket();
last_ping = millis();
}
}
The remaining arduinos use the exact same code, but with two differences:
- only the first one has a reference to the time since last ping; the others only go off when the previous arduino commands them to.
- each arduino has a different IP Address (but same port).
However, when I run this code, the first arduino always sends a message after 5 seconds, but the second arduino never reacts to it. The second arduino just repeats:
Checking polling server.
Contents of packet:
so I can only assume that, somehow, the message isn't getting to the final arduino. Some things I've checked:
-both arduinos are on the network, I can ping them.
-the first arduino is successfully sending all of the appropriate confirmations for reading the sonar and sending the UDP message
what could be causing this?
thanks