我正在使用一台使用2台计算机和连接声纳的arduino的系统;各自的功能如下:
第一台计算机是命令计算机',并向arduinos发出命令以进行传感器测量。
以太网arduino接受来自命令计算机的命令,然后将测量结果发送到操作计算机。
操作计算机根据测量结果执行操作。
所有通信都是通过python套接字模块和arduino以太网库完成的。
出于测试目的,我在同一台计算机上模拟命令和操作计算机但使用不同的套接字。命令计算机由client.py模拟,Action计算机由server.py模拟。如果我将它们直接指向对方(跳过arduino),一切都按预期工作。
然而,当我在中间添加arduino时,我遇到的问题是arduino没有响应发送给它的所有命令,整个系统都会变慢。
我无法弄清楚如何开始对此进行故障排除 - 我无法判断arduino是否能够快速连续处理这么多请求,或者我是否可能以笨重的方式处理消息,导致套接字过于频繁地不可用。任何建议将不胜感激 - 代码如下。
client.py
import socket
import time
while True:
try:
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(("192.168.0.250", 10220))
#client_socket.connect(("192.168.0.100", 8220))
data = "GET\nSONAR\n\n"
print 'send to server: ' + data
client_socket.send(data)
#receive = client_socket.recv(2048)
#print receive
client_socket.close()
time.sleep(1)
except Exception as msg:
print msg
这谈到simpleSonarTest.ino:
#include <avr/wdt.h>
#include <SPI.h>
#include <Ethernet.h>
#include <MyClient.h>
#include <SoftwareSerial.h>
//localClient parameters, for sending data to the server.
byte mac[] = {0x90, 0xA2, 0xDA, 0x0F, 0x03, 0x58};
byte ip[] = {192,168,0,250};
byte server[] = {192, 168, 0, 100};
int serverPort = 8220;
MyClient* localClient;
//Server parameters, for acting like a server.
int localPort = serverPort + 1000;
int pollPort = serverPort + 2000;
EthernetServer localServer = EthernetServer(localPort);
EthernetServer pollServer = EthernetServer(pollPort);
//sonar stuff
String content_string;
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 time;
void setup() {
Serial.begin(9600);
Ethernet.begin(mac, ip);
wdt_enable(WDTO_8S);
localClient = new MyClient(mac, ip);
localClient->connect(server, serverPort);
pollServer.begin();
for(int i = 0; i < NUM_SONARS; i++) {
pinMode(sonarPin[i], INPUT);
}
pinMode(triggerPin, OUTPUT);
digitalWrite(triggerPin, LOW);
time = 0;
}
void loop() {
wdt_reset();
time = millis();
EthernetClient pollClient = pollServer.available();
if (pollClient) {
boolean currentLineIsBlank = true;
String receivingString = "";
while (pollClient.connected()) {
//while the socket is open
if(pollClient.available()) {
//and there is something to read on the port, then read the available characters
char c = pollClient.read();
receivingString += c;
//share with the serial monitor:
if (c == '\n' && currentLineIsBlank) {
pollClient.println("Received message.");
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);
// parse the incoming data
String command = split(receivingString,'\n',0);
String payload = split(receivingString,'\n',1);
String key = split(payload,'=',0);
String value = split(payload,'=',1);
//PARSE THE KEY AND VALUE NOW
if(command == "GET") {
if(key == "SONAR") {
pingSonars();
}
}
pollClient.stop();
Serial.println("Closing poll client connection.");
}
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);
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:
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:
Serial.print("Sonar ");
Serial.print(i);
Serial.println(" falling!");
sonarState[i] = 0;
}
//always respond to a poll with the current state
content_string = "PUT\nSONAR ";
content_string += String(i);
content_string += "= ";
content_string += String(sonarState[i]);
content_string += "\n\n";
localClient->post_request(content_string);
}
}
将PUT消息发送到server.py
import socket
host = '192.168.0.100'
port = 8220
address = (host, port)
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind((address))
server_socket.listen(5)
while True:
try:
print "Listening for client . . ."
conn, address = server_socket.accept()
print "Connected to client at ", address
#pick a large output buffer size because i dont necessarily know how big the incoming packet is
output = conn.recv(2048);
if output:
print "Message received from client:"
print output
#conn.send("This is a response from the server.")
conn.close()
#print "Test message sent and connection closed."
except KeyboardInterrupt:
print
print "Stop."
break
作为参考,MyClient是以太网的包装器,用于发送HTTP样式(但不符合HTTP)的消息:
#include <WProgram.h>
#include "MyClient.h"
MyClient::MyClient(byte* mac_address, byte* ip_address) {
Serial.println("Initializing HTTP Client...");
Ethernet.begin(mac_address, ip_address);
Serial.print("My IP address: ");
Serial.println(Ethernet.localIP());
delay(1000);
debug = true;
}
void MyClient::connect(byte* server_address, int port) {
//server = server_address;
Serial.print("Attempting to connect to server at ");
Serial.print(server_address[0]);
Serial.print(".");
Serial.print(server_address[1]);
Serial.print(".");
Serial.print(server_address[2]);
Serial.print(".");
Serial.print(server_address[3]);
Serial.print("...");
while(!client.connect(server_address, port)) {
;
}
Serial.println("Connected to server!");
}
void MyClient::disconnect() {
client.stop();
}
bool MyClient::connected() {
return client.connected();
}
void MyClient::get_request(String resource) {
if(debug) {
Serial.println("Submitting GET request.");
}
// Make a HTTP request:
client.print("GET ");
client.print(resource);
client.println(" HTTP/1.1");
print_host(server);
client.println("User-Agent: sdfSensorClient/0.1");
client.println("Connection: close");
client.println();
}
void MyClient::post_request(String content) {
if(debug) {
Serial.println("Making a POST request.");
}
content += "[/TCP]";
client.println(content);
if(debug) {
Serial.println("Posted:");
Serial.println(content);
}
}
void MyClient::print_host(byte* host) {
client.print("Host: ");
client.print(host[0]);
client.print(".");
client.print(host[1]);
client.print(".");
client.print(host[2]);
client.print(".");
client.println(host[3]);
}
void MyClient::get_response() {
while (client.available()) {
char c = client.read();
if(debug) {
Serial.print(c);
}
}
}
bool MyClient::get_status() {
return client.connected();
}
void MyClient::set_debug(bool status) {
debug = status;
}