Surface Mount ATMega328p-AU sensor board.
-
I have been working on a project that will integrate a wide range of sensors into a nice surface mount package for the ATMega328p-au (Arduino chip). I am currently waiting on these boards from OSH Park so they are untested at the moment. I will post an update once it has been tested.
Board layout:
-
3-Pin Headers: Each of the 3 pin headers are attached to VCC and Ground with I/O pin in the middle. RELAY = D6, FLOW = D5, A_TEMP = D4, W_TEMP = D3, PRESSURE = A0
-
4-Pin Headers: Most of the 4 pin headers are for I2C devices and go VCC - SCL - SDA - GND. The exception is TTL which is VCC - RX - TX - GND.
-
Programer header: Top to bottom >> GND - NC - VCC - TX - RX - DTR
-
L1-L3 are WS2812B addressable RGB LED's.
The board was designed in eagleCAD if anyone was interested in the sch or brd files.
Link to OSH Park: https://oshpark.com/shared_projects/IVovQwgz
![Alt text][1]
[1]: https://644db4de3505c40a0444-327723bce298e3ff5813fb42baeefbaa.ssl.cf1.rackcdn.com/uploads/project/top_image/IVovQwgz/i.png "SMD Sensor Board"
-
-
I like it, looking forward to seeing how your testing goes.
-
I am glad to report that my first attempt at designing a board went well overall. The project/boards linked in my above post works as is, but I would make a few modifications on future boards. Some of the modifications I will hopefully implement soon are:
- Addition of holes so the board can be mounted to a project enclosure.
- Combine the Water/Air Temp sensors onto a single pin to the ATMega328p along with adding a resistor between the data and VCC. Unfortunately, I did not realize that DS18B20's could be chained together to save on pins, or that it needs to have a pull-up resistor.
- Drop the number of I2C pin connections to one or two. In addition to this I will probably also make a simple breakout board for expanding the number of connections as needed.
- Include I2C pull up resistors. It has been functioning without any issues without them, but I should have put them on the board.
The Sketch I have created and have running includes the following sensors so far:
- Atlas Scientific pH sensor and probe
- Atlas Scientific ORP sensor and probe
- (2)Dallas DS18B20 for water and air temp.
- Relay for pool pump
- MPX5500DP pressure sensor to monitor water at the filter pressure
- A 4 line 20 character LCD display currently showing temps/ORP/pH
The sketch is sending the data to my MIOS as expected. However, when I turn the relay on I have noticed the message is broadcast quite a few times. When debugging is active it seemed that the incoming message would display around a hundred times (I never actually counted the number of times). Is such a large number of attempts to send the message normal? Any feedback or recommendations are welcome.
Note: I do not have the arduino bootloader running on my boards. I am using the Visual Micro addin for AtmelStudio and an MKII ISP to program the boards.
#include <SPI.h> #include <MySensor.h> #include <Wire.h> #include <DallasTemperature.h> #include <OneWire.h> #include <LiquidCrystal_I2C.h> /*#### MySensor Node definitions ####*/ #define NODE_ID 2 #define PRES_CHILD 0 #define WTEMP_CHILD 1 #define ATEMP_CHILD 2 #define RELAY_CHILD_ID 3 #define PH_CHILD_ID 4 #define ORP_CHILD_ID 5 /*#### Arduino Pin definitions #####*/ #define MPX5500DP_PIN 0 // A0 - MPX5500DP pin #define WTEMP_PIN 3 // D3 - Dallas one wire temp sensor #define ATEMP_PIN 4 // D4 - Dallas one wire temp sensor #define PUMP_RELAY 6 // D6 - Relay Pin /*#### Program definitions #####*/ #define PH_I2C 99 //default I2C ID number for EZO pH Circuit. #define ORP_I2C 98 //default I2C ID number for EZO ORP Circuit. #define NUMBER_OF_RELAYS 1 // Total number of attached relays #define RELAY_ON 1 // GPIO value to write to turn on attached relay #define RELAY_OFF 0 // GPIO value to write to turn off attached relay #define MAX_ATTACHED_DS18B20 16 // Define the max number of DS18B20 per pin #define LCD_I2C 0x3F // I2C address of the LCD screen /*#### Program variables #####*/ unsigned long SLEEP_TIME = 5000; // Sleep time between reads (in mili-seconds) int delay_count = 0; int periodUpdate = 0; LiquidCrystal_I2C lcd(LCD_I2C, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // Set the LCD I2C address //temperature variables OneWire waterOneWire(WTEMP_PIN); DallasTemperature wSensors(&waterOneWire); OneWire airOneWire(ATEMP_PIN); DallasTemperature aSensors(&airOneWire); float atemperature = 0; float wtemperature = 0; float lastPressure = -1; float lastWTemp = -1; float lastATemp = -1; // &&&& pH and ORP &&&& byte code=0; //used to hold the I2C response code. char I2C_data[10]; //we make a 20 byte character array to hold incoming data from the circuit. byte in_char=0; //used as a 1 byte buffer to store in bound bytes from the pH Circuit. byte i=0; //counter used for ph_data array. float ph_float = 0; //float var used to hold the float value of the pH. float ORP_float = 0; //float var used to hold the float value of the ORP. float last_ph_float = 1; //float var used to hold the float value of the last pH. float last_ORP_float = 1; //float var used to hold the float value of the last ORP. /*#### My Sensors #####*/ boolean metric; MySensor gw; //Message definitions MyMessage pHMsg(PH_CHILD_ID, V_VAR1); MyMessage orpMsg(ORP_CHILD_ID, V_VAR1); MyMessage wTempMsg(WTEMP_CHILD, V_TEMP); MyMessage aTempMsg(ATEMP_CHILD, V_TEMP); MyMessage pressureMsg(PRES_CHILD, V_PRESSURE); /*#### Program #####*/ void setup() { wSensors.begin(); aSensors.begin(); gw.begin(incomingMessage, NODE_ID, true); // Send the sketch version information to the gateway and Controller gw.sendSketchInfo("Sensor Node AlphaMax", "0.1"); // Update Node name for each node -- Update version number for each update. // Register sensors to gw (they will be created as child devices) gw.present(PRES_CHILD, S_BARO); gw.present(WTEMP_CHILD, S_TEMP); gw.present(ATEMP_CHILD, S_TEMP); gw.present(PH_CHILD_ID, S_CUSTOM); gw.present(ORP_CHILD_ID, S_CUSTOM); gw.present(RELAY_CHILD_ID, S_LIGHT); metric = gw.getConfig().isMetric; // getConfig() returns true for metric, false for imperial pinMode(PUMP_RELAY, OUTPUT); // Then set relay pins in output mode digitalWrite(PUMP_RELAY, gw.loadState(RELAY_CHILD_ID)?RELAY_ON:RELAY_OFF); // Set relay to last known state (using eeprom storage) lcd.begin(20,4); // Initialize the lcd for 20 chars 4 lines lcd.clear(); // Clear LCD screen before use } void loop() { gw.process(); //Get temperature aSensors.requestTemperatures(); atemperature = static_cast<float>(static_cast<int>((gw.getConfig().isMetric?aSensors.getTempCByIndex(0):aSensors.getTempFByIndex(0)) * 100.)) / 100.; wSensors.requestTemperatures(); wtemperature = static_cast<float>(static_cast<int>((gw.getConfig().isMetric?wSensors.getTempCByIndex(0):wSensors.getTempFByIndex(0)) * 100.)) / 100.; //Get pressure float pressure = analogRead(MPX5500DP_PIN); //MPX5500DP Pressure sensor //Get ph and ORP atlas(PH_I2C); atlas(ORP_I2C); //Update LCD Screen printscreen(); //Update VERA when needed. if (ph_float != last_ph_float) { gw.send(pHMsg.set(ph_float,2)); last_ph_float = ph_float; } if (ORP_float != last_ORP_float) { gw.send(orpMsg.set(ORP_float,1)); last_ORP_float = ORP_float; } //Periodic updates were used when LCD display was on another node //since they do not appear to be hurting anything I left them in. if (wtemperature != lastWTemp | periodUpdate == 250000) { gw.send(wTempMsg.setDestination(0).set(wtemperature,1)); lastWTemp = wtemperature; } if (atemperature != lastATemp | periodUpdate == 500000) { gw.send(aTempMsg.setDestination(0).set(atemperature,1)); lastATemp = atemperature; } if (pressure != lastPressure | periodUpdate == 750000) { gw.send(pressureMsg.set(pressure, 0)); lastPressure = pressure; } if(periodUpdate >= 750000) { periodUpdate = 0; } periodUpdate++; } //This function is used to handle data to and from the ORP and pH sensors void atlas(int address){ Wire.beginTransmission(address); //call the circuit by its ID number. Wire.write('R'); //transmit the command that was sent through the serial port. Wire.endTransmission(); //end the I2C data transmission. for(int k=0;k<=140;k++) // Need to delay 1.4 seconds between sending read command { // and requesting data. This for loop keeps delays between gw.process(); // processing incoming messages short. delay(10); } Wire.requestFrom(address,20,1); //call the circuit and request 20 bytes (this may be more then we need). code=Wire.read(); //the first byte is the response code, we read this separately. switch (code){ //switch case based on what the response code is. case 1: //decimal 1. Serial.println("Success"); //means the command was successful. break; //exits the switch case. case 2: //decimal 2. Serial.println("Failed"); //means the command has failed. break; //exits the switch case. case 254: //decimal 254. Serial.println("Pending"); //means the command has not yet been finished calculating. break; //exits the switch case. case 255: //decimal 255. Serial.println("No Data"); //means there is no further data to send. break; //exits the switch case. } while(Wire.available()){ //are there bytes to receive. in_char = Wire.read(); //receive a byte. I2C_data[i]= in_char; //load this byte into our array. i+=1; //incur the counter for the array element. if(in_char==0){ //if we see that we have been sent a null command. i=0; //reset the counter i to 0. Wire.endTransmission(); //end the I2C data transmission. break; //exit the while loop. } } Serial.println(I2C_data); //print the data. if(address == PH_I2C) { ph_float = atof(I2C_data); } else if(address == ORP_I2C) { ORP_float = atof(I2C_data); } else Serial.print("No address match!!!!"); } void incomingMessage(const MyMessage &message) { // We only expect one type of message from controller. But we better check anyway. if (message.type==V_LIGHT) { // Change relay state digitalWrite(PUMP_RELAY, message.getBool()?RELAY_ON:RELAY_OFF); // Store state in eeprom gw.saveState(RELAY_CHILD_ID, message.getBool()); // Write some debug info Serial.print("Incoming change for sensor:"); Serial.print(message.sensor); Serial.print(", New status: "); Serial.println(message.getBool()); } } void printscreen() { lcd.clear(); lcd.setCursor(0,0); lcd.print("Water Temp "); lcd.setCursor(11,0); lcd.print(wtemperature); lcd.setCursor(0,1); lcd.print("Air Temp"); lcd.setCursor(11,1); lcd.print(atemperature); lcd.setCursor(0,2); lcd.print("pH"); lcd.setCursor(11,2); lcd.print(ph_float); lcd.setCursor(0,3); lcd.print("ORP"); lcd.setCursor(11,3); lcd.print(ORP_float); }
-
The relay switch causes "noise" into the power lines, which drives the radio (mostly) and arduino (sometimes) crazy.
How are you powering your arduino / radio?
-
I have been using an old(cheap) wall-to-USB power supply. I'll give it a try with a beefier supply and let you know the results I get.