一乐电子

一乐电子百科

 找回密码
 请使用微信账号登录和注册会员

QQ登录

只需一步,快速开始

快捷登录

手机号码,快捷登录

搜索
查看: 8448|回复: 20
收起左侧

ATMEGA8L最小系统+ENC28J60 UDP传输+两位数码管显示的温湿度监控模块

[复制链接]
发表于 2013-3-3 12:02 | 显示全部楼层 |阅读模式
经过几天摸索,调通了ENC28J60的UDP传输代码,用ATMEGA8L最小系统搭建了个基于UDP传输和两位数码管显示的温湿度监控下位机,可以用PC作为上位机组建多机房的远程温湿度和设备状态监控系统。ATMEGA8L熔丝设定为8MHz,用内部RC振荡器,USB端口取电,经2个二极管串接降压到3.5V左右为ATMEGA8L和ENC28J60供电,电路组装在洞洞板上,预留了ISP编程接口(兼连接ENC28J60模块的接口),用了一个ADSL线路分离器的外壳做模块的外壳,成本不到30元。
附上代码和烧录文件、VB编的上位机测试程序。
  1. /*
  2. This sketch receives humidity and temperature from sensor DHT11,
  3. display on two digits seven-segment LED and send UDP message to remote server, prints them to the serial port.
  4. The code can only compily by IDE 002X
  5. Created 28 Feb 2013, by Chen JW. [email]superid888@gmail.com[/email]
  6. */

  7. #include "EtherShield.h"
  8. static uint8_t mymac[6] = { 0x54,0x55,0x58,0x10,0x00,0x25};
  9. static uint8_t myip[4] = { 192,168,2,23};
  10. static uint8_t broadcastip[4] = { 192,168,2,255};
  11. // DestPort 1001, SrcPort 1000
  12. #define DEST_PORT_L  0xE9
  13. #define DEST_PORT_H  0x03
  14. #define SRC_PORT_L  0xE8
  15. #define SRC_PORT_H  0x03
  16. const char iphdr[] PROGMEM ={ 0x45,0,0,0x82,0,0,0x40,0,0x20}; // 0x82 is the total

  17. struct UDPPayload {
  18. uint8_t data[2];
  19. };
  20. UDPPayload udpPayload;

  21. // Packet buffer, must be big enough to packet and payload
  22. #define BUFFER_SIZE 150
  23. static uint8_t buf[BUFFER_SIZE+1];

  24. EtherShield es=EtherShield();

  25. // bits representing segments A through G (and decimal point) for numerals 0-9
  26. const int numeral[10] = {
  27. //ABCDEFG /dp
  28. B11111100, // 0
  29. B01100000, // 1
  30. B11011010, // 2
  31. B11110010, // 3
  32. B01100110, // 4
  33. B10110110, // 5
  34. B10111110, // 6
  35. B11100000, // 7
  36. B11111110, // 8
  37. B11110110, // 9
  38. };
  39. // pins for decimal point and each segment
  40. // dp,G,F,E,D,C,B,A
  41. const int segmentPins[] = { 9,8,7,6,5,4,3,2};
  42. const int nbrDigits= 2; // the number of digits in the LED display
  43. //dig 1 2
  44. const int digitPins[nbrDigits] = { A4,A5};
  45. int dppin=A3; //set the decimal point link to PIN A3

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

  49. char string1[2];//Humd
  50. char string2[2];//Temp



  51. void setup(){

  52. Serial.begin(19200);

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

  56. for(int i=0; i < 8; i++)
  57. pinMode(segmentPins[i], OUTPUT); // set segment and DP pins to output
  58. for(int i=0; i < nbrDigits; i++)
  59. pinMode(digitPins[i], OUTPUT);
  60. }


  61. void loop(){

  62. int chk = DHT11.read(DHT11PIN);

  63.   Serial.print("Read sensor: ");
  64.   switch (chk)
  65.   {
  66.    case DHTLIB_OK:
  67.                 Serial.println("OK");
  68.                 break;
  69.     case DHTLIB_ERROR_CHECKSUM:
  70.                 Serial.println("Checksum error");
  71.                 break;
  72.     case DHTLIB_ERROR_TIMEOUT:
  73.                 Serial.println("Time out error");
  74.                 break;
  75.     default:
  76.                 Serial.println("Unknown error");
  77.                 break;
  78.   }

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

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

  83. udpPayload.data[0] =humd;
  84. udpPayload.data[1] =temp;
  85. broadcastData() ;
  86. Serial.println("Data send over UDP.");

  87. //Display on 7segment
  88.   int counter1=200;
  89. while(counter1)
  90. {
  91.     counter1--;
  92. //    showNumber(DHT11.humidity);
  93. showNumber(humd);
  94.    }
  95.     counter1=200;
  96. while(counter1)
  97. {
  98.     counter1--;
  99.     analogWrite(dppin,0);
  100. //    showNumber(DHT11.temperature-2);
  101. showNumber(temp);
  102.     analogWrite(dppin,200);
  103.    }
  104. }

  105. // Broadcast the data in the udpPayload structure
  106. void broadcastData( void ) {
  107.   uint8_t i=0;
  108.   uint16_t ck;
  109.   // Setup the MAC addresses for ethernet header
  110.   while(i<6){
  111.     buf[ETH_DST_MAC +i]= 0xff; // Broadcsat address
  112.     buf[ETH_SRC_MAC +i]=mymac[i];
  113.     i++;
  114.   }
  115.   buf[ETH_TYPE_H_P] = ETHTYPE_IP_H_V;
  116.   buf[ETH_TYPE_L_P] = ETHTYPE_IP_L_V;
  117.   es.ES_fill_buf_p(&buf[IP_P],9,iphdr);

  118.   // IP Header
  119.   buf[IP_TOTLEN_L_P]=28+sizeof(UDPPayload);
  120.   buf[IP_PROTO_P]=IP_PROTO_UDP_V;
  121.   i=0;
  122.   while(i<4){
  123.     buf[IP_DST_P+i]=broadcastip[i];
  124.     buf[IP_SRC_P+i]=myip[i];
  125.     i++;
  126.   }
  127.   es.ES_fill_ip_hdr_checksum(buf);
  128.   buf[UDP_DST_PORT_H_P]=DEST_PORT_H;
  129.   buf[UDP_DST_PORT_L_P]=DEST_PORT_L;
  130.   buf[UDP_SRC_PORT_H_P]=SRC_PORT_H;
  131.   buf[UDP_SRC_PORT_L_P]=SRC_PORT_L; // lower 8 bit of src port
  132.   buf[UDP_LEN_H_P]=0;
  133.   buf[UDP_LEN_L_P]=8+sizeof(UDPPayload); // fixed len
  134.   // zero the checksum
  135.   buf[UDP_CHECKSUM_H_P]=0;
  136.   buf[UDP_CHECKSUM_L_P]=0;
  137.   // copy the data:
  138.   i=0;
  139.   // most fields are zero, here we zero everything and fill later
  140.   uint8_t* b = (uint8_t*)&udpPayload;
  141.   while(i< sizeof( UDPPayload ) ){
  142.     buf[UDP_DATA_P+i]=*b++;
  143.     i++;
  144.   }
  145.   // Create correct checksum
  146.   ck=es.ES_checksum(&buf[IP_SRC_P], 16 + sizeof( UDPPayload ),1);
  147.   buf[UDP_CHECKSUM_H_P]=ck>>8;
  148.   buf[UDP_CHECKSUM_L_P]=ck& 0xff;
  149.   es.ES_enc28j60PacketSend(42 + sizeof( UDPPayload ), buf);
  150. }

  151. void showNumber( int number)
  152. {
  153. if(number == 0)
  154. showDigit( 0, nbrDigits-1) ; // display 0 in the rightmost digit
  155. else
  156. {
  157. // display the value corresponding to each digit
  158. // leftmost digit is 0, rightmost is one less than the number of places
  159. for( int digit = nbrDigits-1; digit >= 0; digit--)
  160. {
  161. if(number > 0)
  162. {
  163. showDigit( number % 10, digit) ;
  164. number = number / 10;
  165. }
  166. }
  167. }
  168. }
  169. // Displays given number on a 7-segment display at the given digit position
  170. void showDigit( int segnumber, int digit)
  171. {
  172. digitalWrite( digitPins[digit], HIGH );
  173. for(int segment = 1; segment <8; segment++)
  174. {
  175. boolean isBitSet = bitRead(numeral[segnumber], segment);
  176. // isBitSet will be true if given bit is 1

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

  178. digitalWrite( segmentPins[segment], isBitSet);
  179. }
  180. delay(5);
  181. digitalWrite( digitPins[digit], LOW );
  182. }

  183. // End
复制代码

upper_computer.zip (6.92 KB, 下载次数: 788)

DHT11_7segLED_ok_IDE023_ok_noser_ino.cpp.zip (4.12 KB, 下载次数: 731)

DHT11_7segLED_ok_IDE023_ok_conv_ino.cpp.zip (5.76 KB, 下载次数: 755)

总装图.jpg

温度显示效果.jpg

湿度显示效果.jpg

分解图.jpg

背面.jpg

ISP烧录.png




















评分

参与人数 2一乐金币 +105 收起 理由
alone + 5 很给力!
199003326 + 100 很给力!

查看全部评分

发表于 2013-3-3 12:06 | 显示全部楼层
不错,收藏了。
发表于 2013-3-3 12:50 | 显示全部楼层
写的太好了 果断收藏了
发表于 2013-3-3 13:12 | 显示全部楼层
以下是在网上搜索到的、关于【ENC28j60 网络模块】的文字介绍:

      ENC28j60 网络模块是带有行业标准串行外设接口(SerialPeripheral Interface,SPI)的独立以太网控制器。 它可作为任何配备有SPI 的控制器的以太网接口。ENC28J60 符合IEEE 802.3 的全部规范,采用了一系列包过滤机制以对传入数据包进行限制。 同时ENC28j60 网络模块还提供了一个内部DMA 模块,以实现快速数据吞吐和硬件支持的IP校验和计算,与主控制器的通信通过两个中断引脚和SPI 实现,数据传输速率高达10 Mb/s,两个专用的引脚用于连接LED,进行网络活动状态指示。
      ENC28j60 网络模块使用MicroChip公司高性能SPI总线的单芯片网络接口芯片IEEE 802.3 兼容的以太网控制器 集成MAC 和10 BASE-T PHY,支持全双工和半双工模式,配置内置网络变压器的RJ45模块HR911102A,进一步缩小体积。ENC28j60 网络模块使用标准的100mil间距的双列2*5插针方便与用户mcu连接,单电源3.3V供电,配备LED电源指示灯,引脚电平兼容5V标准。
      ENC28j60 网络模块产品特点:
      1、ENC28J60以太网芯片,SOP28封装
      2、IEEE 802.3 兼容的以太网控制器 集成MAC 和10 BASE-T PHY
      3、支持全双工和半双工模式
      4、SPI接口,SPI时钟可高达20MHZ,最高速度可达10 Mb/s 的SPI 接口
      5、100mil间距2*5 连接插针,可方便与MCU连接
      6、内置隔离变压器RJ45接头HR911102A
      7、Power, Link and Activity LEDs
      8、单电源供电: +3.3V
      9、25Mhz 晶振
      10、PCB尺寸:35mm x 55mm x 20mm

      ENC28j60 网络模块由七个主要功能模块组成:
      1. SPI 接口——充当主控制器和ENC28J60 之间通信通道。
      2. 控制寄存器——用于控制和监视ENC28J60。
      3. 双端口RAM缓冲器——用于接收和发送数据包。
      4. 判优器——当DMA、发送和接收模块发出请求时对RAM 缓冲器的访问进行控制。
      5. 总线接口——对通过SPI 接收的数据和命令进行解析。
      6. MAC (Medium Access Control)模块——实现符合IEEE 802.3 标准的MAC 逻辑。
      7. PHY(物理层)模块——对双绞线上的模拟数据进行编码和译码。
发表于 2013-3-3 14:11 | 显示全部楼层
也不清楚ENC28J60模块现在多少钱了?
传感器类要组网才有意义,这个方案组网的话成本太高
单片机+从无线数传模块-》主无线数传模块+单片机+串口通讯-》无线路由

点评

这主意不错,如果空间足够的话争取加上去。  发表于 2013-3-3 19:23
发表于 2013-3-3 14:31 | 显示全部楼层
M8虽说玩不起协议栈,但是你可以考虑在线更改地址ip后(放在eeprom,flash都行),自动重启生效。

点评

这主意不错,如果空间足够的话争取加上去。  发表于 2013-3-3 19:24
发表于 2013-3-3 19:08 | 显示全部楼层
UDP无爱啊,网上也只有基于TCP的网页控制LED的例程,买了个野火的开发板,带的LWIP例程还不错。。

点评

以前用的上位机是UDP传输的,觉得编程简单,这次就用了UDP,没想到Arduino第三方的库文件那么不靠谱。  发表于 2013-3-3 19:27
 楼主| 发表于 2013-3-3 19:22 | 显示全部楼层
文句子 发表于 2013-3-3 14:11 static/image/common/back.gif
也不清楚ENC28J60模块现在多少钱了?
传感器类要组网才有意义,这个方案组网的话成本太高
单片机+从无线数 ...

ENC28J60模块现在便宜了,才¥18,Arduino推荐的W5100有硬件堆栈和官方库,编程容易,但要¥45,所以选了ENC28J60,加上DHT11 ¥6.5,ATMEGA8L ¥4.5,杂七杂八不到一个节点30元不能算贵吧,几年前用周立功ZNET200T网络模块+51MCU+SHT11做的温湿度监控,一个节点成本就近400。

发表于 2013-3-3 20:10 | 显示全部楼层
串口服务器或者模块现在也不便宜
这个不是加法,组起网来是星形连接,是乘法,
2块一米的网线
还不如走个422总线呢
发表于 2013-3-3 22:08 | 显示全部楼层
漏网之鱼 发表于 2013-3-3 19:22 static/image/common/back.gif
ENC28J60模块现在便宜了,才¥18,Arduino推荐的W5100有硬件堆栈和官方库,编程容易,但要¥45,所以选了 ...

Arduino只能说其实就只是个玩具而已,并不适合用于电子产品开发。

本版积分规则

QQ|一淘宝店|手机版|商店|电子DIY套件|一乐电子 ( 粤ICP备09076165号 ) 公安备案粤公网安备 44522102000183号

GMT+8, 2024-3-29 18:49 , Processed in 0.068304 second(s), 44 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表