superid888 发表于 2013-2-21 00:16:27

ethercard用于UDP发送的奇怪问题

本帖最后由 superid888 于 2013-3-2 16:56 编辑

想用Arduino+ENC28J60+DHT11+两位7段数码管做一个带显示的温湿度监控下位机,各硬件和子模块测试正常,ENC28J60的CS接在D10,实测供电电压为3.25V,IDE用的1.03版,EtherCard用的是最新版,所有功能在开winshake抓包时正常,用上位机能正确显示温湿度,但不开开winshake时上位机就接收不到UDP数据,请问可能是什么问题?谢谢!
附上代码和测试的上位机程序

#include <EtherCard.h>
static byte mymac[] = { 0x74,0x69,0x69,0x2D,0x30,0x31 };
static byte myip[] = {192,168,2,23};
static byte gwip[] = {192,168,23,254};
byte Ethernet::buffer;
static byte destip[]= {192,168,2,10};
static int myport=1000,destport=1001;

// bits representing segments A through G (and decimal point) for numerals 0-9
const int numeral = {
//ABCDEFG /dp
B11111100, // 0
B01100000, // 1
B11011010, // 2
B11110010, // 3
B01100110, // 4
B10110110, // 5
B10111110, // 6
B11100000, // 7
B11111110, // 8
B11110110, // 9
};
// pins for decimal point and each segment
// dp,G,F,E,D,C,B,A
const int segmentPins[] = { 9,8,7,6,5,4,3,2};
const int nbrDigits= 2; // the number of digits in the LED display
//dig 1 2
const int digitPins = { A4,A5};
int dppin=A3; //set the decimal point link to PIN A3

#include <dht11.h>
dht11 DHT11;
#define DHT11PIN A0 //DHT11 PIN 3 连接UNO A0

char string1;//温度值字符串变量
char string2;//温度值字符串变量

void setup()
{
Serial.begin(19200);

if (ether.begin(sizeof Ethernet::buffer, mymac, 10) == 0)
    Serial.println( "Failed to access Ethernet controller");
if (!ether.staticSetup(myip))
    Serial.println("Failed to set IP address");
   
   //    ether.setGwIp(gwip);
   
for(int i=0; i < 8; i++)
pinMode(segmentPins, OUTPUT); // set segment and DP pins to output
for(int i=0; i < nbrDigits; i++)
pinMode(digitPins, OUTPUT);

}

void loop()
{

int chk = DHT11.read(DHT11PIN);

Serial.print("Read sensor: ");
switch (chk)
{
   case DHTLIB_OK:
                Serial.println("OK");
                break;
    case DHTLIB_ERROR_CHECKSUM:
                Serial.println("Checksum error");
                break;
    case DHTLIB_ERROR_TIMEOUT:
                Serial.println("Time out error");
                break;
    default:
                Serial.println("Unknown error");
                break;
}

int humd=int(DHT11.humidity);
int temp=int(DHT11.temperature-2);

itoa(humd,string1,10);
itoa(temp,string2,10);

ether.sendUdp ((char*) string1, 4, myport, destip, destport);
Serial.println("DATA send by UDP ");
Serial.println(humd);
Serial.println(temp);
//delay(2000);


//Display on 7segment
int counter1=200;
while(counter1)
{
    counter1--;
//    showNumber(DHT11.humidity);
showNumber(humd);
   }
    counter1=200;
while(counter1)
{
    counter1--;
    analogWrite(dppin,0);
//    showNumber(DHT11.temperature-2);
showNumber(temp);
    analogWrite(dppin,200);
   }
}


void showNumber( int number)
{
if(number == 0)
showDigit( 0, nbrDigits-1) ; // display 0 in the rightmost digit
else
{
// display the value corresponding to each digit
// leftmost digit is 0, rightmost is one less than the number of places
for( int digit = nbrDigits-1; digit >= 0; digit--)
{
if(number > 0)
{
showDigit( number % 10, digit) ;
number = number / 10;
}
}
}
}
// Displays given number on a 7-segment display at the given digit position
void showDigit( int segnumber, int digit)
{
digitalWrite( digitPins, HIGH );
for(int segment = 1; segment <8; segment++)
{
boolean isBitSet = bitRead(numeral, segment);
// isBitSet will be true if given bit is 1

//isBitSet = ! isBitSet; // remove this line if common cathode display

digitalWrite( segmentPins, isBitSet);
}
delay(5);
digitalWrite( digitPins, LOW );
}

superid888 发表于 2013-2-21 00:32:33

不知道是ethercard库的原因还是代码的问题,硬件肯定是没问题的,抓包软件起了什么作用,唤醒?

superid888 发表于 2013-2-21 12:29:17

本帖最后由 superid888 于 2013-2-21 12:33 编辑

通过wireshake抓包分析,只要上位机在本端网口137端口发送NetBIOS name service询问包后,就能接收到ethercard的UDP数据,停止发送询问包,就收不到UDP数据,这是什么原因?

superid888 发表于 2013-2-24 10:26:59

用w5100替代enc28j60,用arduino的标准库替代ethercard,发送udp包完全正常,估计ethercard库的软件堆栈还不完善。

superid888 发表于 2013-3-1 08:18:11

本帖最后由 superid888 于 2013-3-1 20:49 编辑

对比w5100和28j60的ethercard库,发现thercard库缺少类似bind这样的函数,请问有什么办法?

superid888 发表于 2013-3-2 16:55:51

问题解决了,是erthercard库的问题,换了另外一个老库EtherShield,在IDE0023下编译通过,代码还变小了,只有不到6K,下一步把代码烧到ATMEGA8L试试看。


/*
This sketch receives humidity and temperature from sensor DHT11,
display on two digits seven-segment LED and send UDP message to remote server, prints them to the serial port.
The code can only compily by IDE 002X
Created 10 Feb 2013, by Chen JW. [email protected]
*/

#include "EtherShield.h"
static uint8_t mymac = { 0x54,0x55,0x58,0x10,0x00,0x25};
static uint8_t myip = { 192,168,2,23};
static uint8_t broadcastip = { 192,168,2,255};
// DestPort 1001, SrcPort 1000
#define DEST_PORT_L0xE9
#define DEST_PORT_H0x03
#define SRC_PORT_L0xE8
#define SRC_PORT_H0x03
const char iphdr[] PROGMEM ={ 0x45,0,0,0x82,0,0,0x40,0,0x20}; // 0x82 is the total

struct UDPPayload {
uint8_t data;
};
UDPPayload udpPayload;

// Packet buffer, must be big enough to packet and payload
#define BUFFER_SIZE 150
static uint8_t buf;

EtherShield es=EtherShield();

// bits representing segments A through G (and decimal point) for numerals 0-9
const int numeral = {
//ABCDEFG /dp
B11111100, // 0
B01100000, // 1
B11011010, // 2
B11110010, // 3
B01100110, // 4
B10110110, // 5
B10111110, // 6
B11100000, // 7
B11111110, // 8
B11110110, // 9
};
// pins for decimal point and each segment
// dp,G,F,E,D,C,B,A
const int segmentPins[] = { 9,8,7,6,5,4,3,2};
const int nbrDigits= 2; // the number of digits in the LED display
//dig 1 2
const int digitPins = { A4,A5};
int dppin=A3; //set the decimal point link to PIN A3

#include <dht11.h>
dht11 DHT11;
#define DHT11PIN A0 //DHT11 PIN 3 == UNO A0

char string1;//Humd
char string2;//Temp

void setup(){

Serial.begin(19200);

es.ES_enc28j60Init(mymac);
//init the ethernet/ip layer:
es.ES_init_ip_arp_udp_tcp(mymac,myip,80);

for(int i=0; i < 8; i++)
pinMode(segmentPins, OUTPUT); // set segment and DP pins to output
for(int i=0; i < nbrDigits; i++)
pinMode(digitPins, OUTPUT);

//delay(1000);
}

void loop(){

int chk = DHT11.read(DHT11PIN);

Serial.print("Read sensor: ");
switch (chk)
{
   case DHTLIB_OK:
                Serial.println("OK");
                break;
    case DHTLIB_ERROR_CHECKSUM:
                Serial.println("Checksum error");
                break;
    case DHTLIB_ERROR_TIMEOUT:
                Serial.println("Time out error");
                break;
    default:
                Serial.println("Unknown error");
                break;
}

int humd=int(DHT11.humidity);
int temp=int(DHT11.temperature-2);

//itoa(humd,string1,10);
//itoa(temp,string2,10);
//byte babb = 0x45;
//string ass = ((char)babb).ToString();

Serial.println(humd);
Serial.println(temp);

udpPayload.data =humd;
udpPayload.data =temp;

//udpPayload.data =string1;
//udpPayload.data =string2;

broadcastData() ;

//Display on 7segment
int counter1=200;
while(counter1)
{
    counter1--;
//    showNumber(DHT11.humidity);
showNumber(humd);
   }
    counter1=200;
while(counter1)
{
    counter1--;
    analogWrite(dppin,0);
//    showNumber(DHT11.temperature-2);
showNumber(temp);
    analogWrite(dppin,200);
   }
}

// Broadcast the data in the udpPayload structure
void broadcastData( void ) {
uint8_t i=0;
uint16_t ck;
// Setup the MAC addresses for ethernet header
while(i<6){
    buf= 0xff; // Broadcsat address
    buf=mymac;
    i++;
}
buf = ETHTYPE_IP_H_V;
buf = ETHTYPE_IP_L_V;
es.ES_fill_buf_p(&buf,9,iphdr);

// IP Header
buf=28+sizeof(UDPPayload);
buf=IP_PROTO_UDP_V;
i=0;
while(i<4){
    buf=broadcastip;
    buf=myip;
    i++;
}
es.ES_fill_ip_hdr_checksum(buf);
buf=DEST_PORT_H;
buf=DEST_PORT_L;
buf=SRC_PORT_H;
buf=SRC_PORT_L; // lower 8 bit of src port
buf=0;
buf=8+sizeof(UDPPayload); // fixed len
// zero the checksum
buf=0;
buf=0;
// copy the data:
i=0;
// most fields are zero, here we zero everything and fill later
uint8_t* b = (uint8_t*)&udpPayload;
while(i< sizeof( UDPPayload ) ){
    buf=*b++;
    i++;
}
// Create correct checksum
ck=es.ES_checksum(&buf, 16 + sizeof( UDPPayload ),1);
buf=ck>>8;
buf=ck& 0xff;
es.ES_enc28j60PacketSend(42 + sizeof( UDPPayload ), buf);
}

void showNumber( int number)
{
if(number == 0)
showDigit( 0, nbrDigits-1) ; // display 0 in the rightmost digit
else
{
// display the value corresponding to each digit
// leftmost digit is 0, rightmost is one less than the number of places
for( int digit = nbrDigits-1; digit >= 0; digit--)
{
if(number > 0)
{
showDigit( number % 10, digit) ;
number = number / 10;
}
}
}
}
// Displays given number on a 7-segment display at the given digit position
void showDigit( int segnumber, int digit)
{
digitalWrite( digitPins, HIGH );
for(int segment = 1; segment <8; segment++)
{
boolean isBitSet = bitRead(numeral, segment);
// isBitSet will be true if given bit is 1

//isBitSet = ! isBitSet; // remove this line if common cathode display

digitalWrite( segmentPins, isBitSet);
}
delay(5);
digitalWrite( digitPins, LOW );
}

// End

SHAGRU 发表于 2013-10-25 11:41:16

我也遇到了同样的问题。我如果不经过路由器,用网线直连电脑和arduino就没问题,如果通过路由连接arduino可以收到udp,但是发送不了udp

但是今天试着用makeUdpReply()又可以,看来是sendUdp()的问题。可能是header哪里有问题。。。:@

SHAGRU 发表于 2013-10-25 11:50:05

果然是header的问题,udprepare()里面的这一行有问题
if ((dip & 0xF0) == 0xE0 || *((long*) dip) == 0xFFFFFFFF)
    EtherCard::copyMac(gPB + ETH_DST_MAC, allOnes);
把它注释之后就可以了。。。。。:lol
页: [1]
查看完整版本: ethercard用于UDP发送的奇怪问题