Complete newbie hardware needed to connect with sensor


#1

Good Afternoon,

I am a complete newbie however I would like to try and use the photon in order to read data from a water meter. The problem is I am so new that even though I have electricians who will help me set up I do not understand the communication terminology to see if I need any other kind of transceivers. Once again please forgive me if I have some terms incorrect as I literally have 0 experience with this stuff and have just spent a week researching.

The sensor has an amplifier that has a communication port. The port has the interface listed as “MODBUS RTU” then it says the interface allows you to configure how the port will be used and lists “MODBUS RTU, Remote Menu, Primo 3.x.” We want to be able to pull readings form the meter and send over wifi so there is no manual reading needed (do not want to control meter)

It is my understanding currently from my research that I need a transceiver in order to receive a MODBUS RTU signal to the photon.

My current thinking is that I will need to get a RS385 transceiver chip (for example MAX485) and connect the amplifier to this chip, then I connect the chip to the photon.

Does this sound correct to you guys? Or is there a way I can directly connect the the photon? I read in the manual that the Primo 3.x setting will output ASCII readings but I am not sure if this can be used by the photon without extra hardware.

Once I know the answer I plan on getting a cheap sensor (any kind of sensor ) that communicates the same way as the water meter does and use that to develop a program and troubleshoot before hooking it up to the large meter

Thank you so much for your help!


#2

please specify your products: what exactly is the sensor and where can I find the datasheet? Please attach any links to the seller / manufacturer.
In the forum you will find a lot of results for the term “Modbus”.
There should even be a library for it.


#3

Thank you ! I am trying to get the numbers from a Badger M2000 water flow meter. https://www.badgermeter.com/business-lines/flow-instrumentation/m2000/ has all of the manuals and specs for it.

I was able to talk to the electrician who is helping em and he did clarify a few things for me, he mentioned that we will be using the RS232 output. So I need to get a chip that will convert RS232 to something the spark can use and hook that to the spark.

I really appreciate your help. I haven’t tackled the programming aspect yet just because I want to get the hardware down and figure out how to get the signal to the spark first without frying it.


#4

@jearle, are you using a Spark Core or a Particle Photon? The easiest way to convert RS232 voltage levels to 3.3v TTL levels used by the Core/Photon is using something like THIS. It can be powered from the Core/Photon and connects to the RX/TX lines on the Particle device. Note that these modules don’t support hardware handshaking signals so you will need a NULL MODEM RS232 cable between the board and the M2000. If supported by the M2000, you could use software flow control.


#5

Thank you so much! I apologize I meant particle photon not the spark.


#6

I’ll throw out an alternative to MODBUS for you…
You may want to consider starting with the Pulse Output.
The meter has terminals for Open Collector, Passive Pulse Outputs.
The Photon would count pulses with an Interrupt.
This only requires 2 wires and a few lines of code.

The Meter can be configured to Output a pulse for every 1 gallon, 10, 100 gallons, etc.
The Photon can track the total Gallons (totalizer) from the ISR, and calculate Flow Rates based on the time between pulses. You can save the Totalizer Variable to EEPROM at your desired schedule. For example: If you write to EEPROM every hour, you would only lose 1 hour’s worth of flow in the event of a Power Failure/reboot of the Photon.

Pulse Output might be the quickest and easiest way to start monitoring that Flow Meter while you investigate and test the MODBUS functionality.


#7

@Rftop Thank you! Unfortunately I am so new to this all that I do not understand your response yet (I have 0 background in electronics or IOT ) however I am going to spend some time today researching your terminology .

I will probably buy pieces to make multiple set ups and let the electricians who will have to install decide what is best for them


#8

This is the datasheet I was looking at.
Start at Page 23.

The Digital Output options are:

image


#9

@Rftop Thanks for all your help! So I can connect JP1 (jumper 1) to the spark directly? Then I can configure output one(JP1) pulses accordingly. Then just work on the code (I know there are a lot of tutorials online for having the photon read water meter pulses just have to go back through them)

EDIT: I apologize I see that the digital output 1 is “terminal 1 and 2” not JP1. However it does list a passive max of 30V DC so I believe I would need to put some kind of shifter in to get the 30V to 3.3 or 5V to go to the spark right?


#10

I believe “Passive” means you supply the voltage, but the Max is 30V.
A Photon Pin would be set as INPUT_PULLUP to supply 3.3V. That pin gets temporarily pulled to Ground during a Pulse Event, triggering your Interrupt to increment a Gallons counter.


#11

Thanks! I will try this


#12

@Rftop

Thank you for all your help so far. This is my first time trying to write code so I spent time learning and used code from the forums already put together.

Right now I don’t have the photon attached to the water meter, I am just trying to get it working and testing using the photo resistor that comes in the kit. (my thinking on this line is i’m just trying to detect the HIGH to LOW state change and count that so I should be able to do this with the photo resister let me know if i’m incorrect.)

I was wondering if you wouldn’t mind looking over my code for me and letting me know if it looks like it should work. The issue I am having right now is that I have the photo resister wired to pin D5 (forwardPin in my code) and the program is working to write to the cloud dashboard every minute, however it is not registering any pulses (i am trying to artificially generate a pulse by covering the photo resister thinking that will move it to low.) I am not sure if I have coded something wrong, or its just that I am using the photo resistor incorrectly to try and do my test.

also another thing I wanted to check with you about is that I need to catch forward pulses and reverse pulses from the meter to make my totalizer. In the code I am trying to do this by having one interrupt set to increase the pulse count by 1 (this will be output one from the meter that I configure to pulse on forward and go to pin D5) and have another interrupt set to subtract the count by one (this will come form the meter output 2 which I will setup to pulse on reverse flow and go to pin D6.) I was wondering if you could look at how I did these interrupts and let me know if I have done it correctly, I didn’t find anything on specifically using two if there was something extra I needed to do.

Thanks!



//following is deifing my pins 
//make sure to set up meter to ouput one pulse per hundred gallons for this to work



int forwardPin = D5; // need to name the pin that forward pulse will be sent to from passive output one . pulse detected here needs to ++ counter 

int reversePin = D6; // need to name the pin that reverse pulse will be sent to from passive output two . I need to make it so a singnal from this pin of a falling state to indicate a pulse was sensed causes the count to --) 

volatile unsigned int waterPulseCount = 0;

unsigned long startMillis;
unsigned long currentMillis;
const unsigned long period = 1000;  //the value is a number of milliseconds, ie 1 second


int gallons = 0;
int t = 0;



int pc = waterPulseCount;
 int msStartHour = 0;



//following I am putting two functions, one will increase the pulse counter by one and the other which is reverse will decrease it by one.
//these functions will be called on by the interrupt, these are my handlers 

void forwardWaterPulseCounter(void){


waterPulseCount++;

}


void reverseWaterPulseCounter(void){


waterPulseCount--;

}


//following setup is to attatch handlers and have then reverse the functions above 

void setup()

{

//this is telling the photon to send voltage to these pins 

pinMode( forwardPin, INPUT_PULLUP);
pinMode( reversePin, INPUT_PULLUP);


  startMillis = millis();  //initial start time
  
  

attachInterrupt(forwardPin, forwardWaterPulseCounter, FALLING) ;




attachInterrupt(reversePin, reverseWaterPulseCounter, FALLING) ;

}



//now is the actual loop that will run constnatly


// add a global variable for the accumulated pulse count
unsigned int accumPulseCount = 0;




void loop()
{
    
    
    currentMillis = millis();  //get the current "time" (actually the number of milliseconds since the program started)
  if (currentMillis - startMillis >= 1000)  //test whether the period has elapsed once per second
  
  
  
  {
    //Read water sensor pulse count and process
    if (waterPulseCount != 0)        // Do nothing if water is not flowing!
    {
   
  

      startMillis = millis();                // Reset base delay time
      detachInterrupt (forwardPin);    // Disable water flow interrupt to read value\
      detachInterrupt (reversePin);    // Disable water flow interrupt to read value
      pc = waterPulseCount;
      waterPulseCount = 0;            // Reset the water pulse counter
attachInterrupt(forwardPin, forwardWaterPulseCounter, FALLING) ;

attachInterrupt(reversePin, reverseWaterPulseCounter, FALLING) ;

      //gallons and adjust for 1 sec offset, if any. if you change meter off of one pulse per hundred gallons you will need to fix this 

      gallons = (pc*100) * (t / 1000);
      accumPulseCount += pc;  // accumulate the readings
      
    }
  }

  if (millis() - msStartHour > 60*1*1000)   //this needs to be 60*60*1000 to do a once an hour output 
  {
    msStartHour = millis(); // start a new hour

    float hourGallons = accumPulseCount * (100);
    accumPulseCount = 0;  // reset counter
    Particle.publish("HourlyWaterReportMeter1", String::format("%4.3f l", hourGallons));
  }
  // for a day act accordingly
}

EDIT: Oh I forgot to mention I did change it to publish to the cloud once a minute just right now while I am messing around and checking if the pulses work .


#13

I haven’t had time to look through your Code yet (plus there are many folks here much more qualified than me). It looks like you have the major concepts.
I’ve never had to deal with the Reverse Flow, but I’d lean towards using unsigned Long Int for the waterPulseCount. You may want to track Positive Counts and Negative Counts separately? Or, UL’s might not be the best for this.

For Testing, don’t use the photo resistor. Just quickly touch Pin D5 or D6 to ground or with a momentary switch. That’s essentially what the Meter will do during a pulse.

I can share some of my code with you that’s written for an Arduino Nano. I’ll first need to remove a lot of the Code that’s specifically for the XBee Mesh Network.

At first glance, You probably shouldn’t reset the waterPulseCount to Zero in loop().
Think of this as the Totalizer Value that will increment for life (or it rolls over).
You can use another variable if you want to perform Hourly, Daily, etc calculations.
Here’s an example of my ISR:


volatile uint32_t waterCount  =      0;   // Totalizer
volatile int waterCountOneInterval = 0;   // Flushed after every Interval / Publish
volatile uint32_t lastWaterIntTime = 0;  //  Time of last Pulse Event


void waterInterrupt() {           // Interrupt for Water Meter

  if (millis() - lastWaterIntTime >= DEBOUNCE_DELAY ) {  // set Debounce similar to the Meter's Pulse width (ms)
    waterCount++;               // Tracks the Total # of Pulses from Meter for eternity.... schedule an EEPROM Backup 
    waterCountOneInterval++;    // Tracks the # of Pulses from Meter for this time interval ONLY - scheduled re-zero from loop()
    newData = true;             // Set Global Flag because interrupt has fired
    lastWaterIntTime = millis();  
  }

}

#14

Thank you so much for all your help! I will look through this and try it

EDIT: I actually just looked back through the output options again because the forward is working but the negative isn’t reacting like I want it to. turns out one of the output options for the pulse is ‘frequency’ which will give me the absolute value so I don’t even have to worry about tracking both myself so I am going to set it up for that