Skip to content
  • OpenHardware.io
  • Categories
  • Recent
  • Tags
  • Popular
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Brand Logo
  1. Home
  2. Hardware
  3. Surface Mount ATMega328p-AU sensor board.
  • Getting Started
  • Controller
  • Build
  • Hardware
  • Download/API
  • Forum
  • Store

Surface Mount ATMega328p-AU sensor board.

Scheduled Pinned Locked Moved Hardware
poolsmd
5 Posts 3 Posters 4.0k Views 6 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • M Offline
    M Offline
    maltimus
    wrote on last edited by maltimus
    #1

    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"

    1 Reply Last reply
    4
    • RJ_MakeR Offline
      RJ_MakeR Offline
      RJ_Make
      Hero Member
      wrote on last edited by
      #2

      I like it, looking forward to seeing how your testing goes.

      RJ_Make

      1 Reply Last reply
      0
      • M Offline
        M Offline
        maltimus
        wrote on last edited by maltimus
        #3

        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);
        }
        
        1 Reply Last reply
        0
        • rvendrameR Offline
          rvendrameR Offline
          rvendrame
          Hero Member
          wrote on last edited by
          #4

          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?

          Home Assistant / Vera Plus UI7
          ESP8266 GW + mySensors 2.3.2
          Alexa / Google Home

          1 Reply Last reply
          0
          • M Offline
            M Offline
            maltimus
            wrote on last edited by
            #5

            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.

            1 Reply Last reply
            0
            Reply
            • Reply as topic
            Log in to reply
            • Oldest to Newest
            • Newest to Oldest
            • Most Votes


            20

            Online

            11.7k

            Users

            11.2k

            Topics

            113.0k

            Posts


            Copyright 2019 TBD   |   Forum Guidelines   |   Privacy Policy   |   Terms of Service
            • Login

            • Don't have an account? Register

            • Login or register to search.
            • First post
              Last post
            0
            • OpenHardware.io
            • Categories
            • Recent
            • Tags
            • Popular