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?
Hello! It looks like you're interested in this conversation, but you don't have an account yet.
Getting fed up of having to scroll through the same posts each visit? When you register for an account, you'll always come back to exactly where you were before, and choose to be notified of new replies (either via email, or push notification). You'll also be able to save bookmarks and upvote posts to show your appreciation to other community members.
With your input, this post could be even better 💗
Register Login