ADC Value with MAX11644

Good morning

I'm relaunching a subject that took time at home and that closed a previous discussion.

Here I have a current analysis system with a MAX11644 chip. I would like to do this integration and the analysis of the data read directly in node-red.
Today I have a python program developed by my electronic integrator.

import time
import sys
import board
import busio
import digitalio
from digitalio import Direction, Pull
from adafruit_mcp230xx.mcp23017 import MCP23017

import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)

from periphery import I2C
def get_adc_value():
	# Open i2c-1 controller
	i2c = I2C("/dev/i2c-1")

	msgs = [I2C.Message([0x61]), I2C.Message([0x00,0x00], read=True)]
	i2c.transfer(0x36, msgs)
	adc_value = (msgs[1].data[0] & 0x0F) <<8 | (msgs[1].data[1])

	# ATTENTION le 4.93 est la tension de ref mesurée à la main
	# pas utile en mode ratiometrique
	adc_value_volt=(adc_value*4.93/4096)
	print("ADC VALUE P4.2: 0x{:04x} , {:0.2f}V".format(adc_value,adc_value_volt))

	msgs = [I2C.Message([0x63]), I2C.Message([0x00,0x00], read=True)]
	i2c.transfer(0x36, msgs)
	adc_value = (msgs[1].data[0] & 0x0F) <<8 | (msgs[1].data[1])

	adc_value_volt=(adc_value*4.93/4096)
	print("ADC VALUE P6.2: 0x{:04x} , {:0.2f}V".format(adc_value,adc_value_volt))

	i2c.close()

How can I make this integration in the flow?

If you could modify the script to send the results over MQTT, you could process the values in Node Red easily.

1 Like

I'm not a coding pro. Do you have any leads or would you be able to make this modification for me?

Why not code in node.js directly?
Here comes a ADS1115 demo written by me, and tested well with my netgate PN6400.
It's possible for you to do a little modification on this and drive MAX11644.
May this help you.

const i2c =  require('/home/node-v14.13.1-linux-armv7l/lib/node_modules/i2c-bus');
const ADS1115_ADDR = 0x4B;

const Conversion_REG = 0x00;
const Config_REG = 0x01;
const Lo_thresh_REG = 0x02;
const Hi_thresh = 0x03;

module.exports = function(RED) {
    function ChvdaPi_ADC_ADS1115(config) {
        RED.nodes.createNode(this,config);
        var node = this;

        const i2c1 = i2c.openSync(1);
        
        node.on('input', function(msg) {
                //0.write configration://OS =1 AINP = AIN1 and AINN = GND   FSR = +-6.144 V  128 SPS  Disable comparator and set ALERT/RDY pin to high-impedance 
                //low byte ahead
                //Single-Shot Mode
                i2c1.writeWordSync(ADS1115_ADDR, 0x01, 0x83D0);//powers up in approximately 25 ��s, resets the OS bit to 0, and starts a single conversion.

                //1.point to result
                var data= i2c1.readWordSync(ADS1115_ADDR, 0x00);
                //console.log("read adc conversion raw result = %d" , data);//low byte ahead
                data = (data  >> 8) + ( (data & 0x00FF) << 8);//swap the 2 bytes
                //console.log("read adc conversion adjusted result = %d" , data);
                var resVolt;
                if(data&0x8000){//sign, < 0
                        resVolt =( ((0x7FFF - (data&0x7FFF) + 1) *6.144 )/32768.0)* (-1);
                }else{//> 0
                        resVolt = ((data ) *6.144 )/32768.0;
                }
        
                //console.log("read adc conversion voltage = %d V" , resVolt );
                msg.payload = resVolt ;
                node.send(msg);
        });
    }
    RED.nodes.registerType("ChvdaPi_ADC_ADS1115",ChvdaPi_ADC_ADS1115);
}

If you use an exec mode to run your script, the output will be available as msg.payload.
So all you need to do is extract the values from what the script outputs.

Seriously? If you have a running system (as it looks like) and no idea of how to do the stuff in another system - why don't you keep your running system?

The code provided is a test code for checking the electronic card.

The rest of my system is in full integration via node red for an MQTT report of input and output command information with a local user interface (maintenance) via a wifi connection to the system, as well as an API for an external third party wanting get information about the operation of the system.

This option has never been implemented on my product and I am looking into this today.

When you run the test code you showed us, does it successfully print the ADC values at the command line?
Please show us an example of it's output.

Exactly how do you hope to use this data within Node-red?

The following code gives me a result identical to this via the "print" lines

I slightly modified the program to be more meaningful

# -*- coding: utf-8 -*-
import time
import sys
import board
import busio
import digitalio
from digitalio import Direction, Pull
from adafruit_mcp230xx.mcp23017 import MCP23017

import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)

from periphery import I2C
while 1==1:
	# Open i2c-1 controller
    i2c = I2C("/dev/i2c-1")

    msgs = [I2C.Message([0x61]), I2C.Message([0x00,0x00], read=True)]
    i2c.transfer(0x36, msgs)
    adc_value = (msgs[1].data[0] & 0x0F) <<8 | (msgs[1].data[1])

	# ATTENTION le 4.93 est la tension de ref mesurée à la main
	# pas utile en mode ratiometrique
    adc_value_volt1=(adc_value*4.93/4096)
    print("MOTEUR: {:0.2f}V".format(adc_value_volt1))

    msgs = [I2C.Message([0x63]), I2C.Message([0x00,0x00], read=True)]
    i2c.transfer(0x36, msgs)
    adc_value2 = (msgs[1].data[0] & 0x0F) <<8 | (msgs[1].data[1])

    adc_value_volt2=(adc_value2*4.93/4096)
    print("ALIM: {:0.2f}V".format(adc_value_volt2))

    time.sleep(1)

I would like to retrieve the values ​​in node red for:
made a graph
export them via MQTT to my supervision

Next step: try this flow. Do you see the output in Node-red?

[{"id":"2ec2d7befa3c2dab","type":"inject","z":"b45544f267d46e64","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":180,"y":140,"wires":[["714f1c657f462976"]]},{"id":"714f1c657f462976","type":"exec","z":"b45544f267d46e64","command":"python3 /home/pi/Documents/Programme/Test4014088.py","addpay":"","append":"","useSpawn":"true","timer":"","winHide":false,"oldrc":false,"name":"","x":490,"y":140,"wires":[["6c5bb63a75d31770"],["77d14fdbf43e2fc9"],[]]},{"id":"6c5bb63a75d31770","type":"debug","z":"b45544f267d46e64","name":"Output","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":810,"y":120,"wires":[]},{"id":"77d14fdbf43e2fc9","type":"debug","z":"b45544f267d46e64","name":"Errors","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":810,"y":160,"wires":[]}]

NB check that the exec node has the right pathname of your script.

Yes

I imagine that now the next step will be output in Json format to be able to retrieve the values ​​and work on them afterwards?
If yes how to do this?

It does seem to be possible to get the data into Node-red.
A couple of things to consider:

If your program runs continuously then it is better to start it via the node-red-daemon rather than exec node. You have to install the daemon node.
The program has to be edited to output JSON.
You could also change it to send the JSON to your MQTT broker. Node-red and any external system could subscribe to them.

Here is a example script which shows how you can print as JSON.
If you run this script via NR Exec, you have to run the output through a JSON parser node.

#! /usr/bin/env python
##############################################
#
# Script to report CPU statistics for Node-Red
#
# jb 02/05/2018
#
##############################################

from collections import OrderedDict
import time
import json
import os
import re

# Find Pi model (This may fail on some Pis?)
file = open("/sys/firmware/devicetree/base/model", "r")
model = file.read().rstrip(' \t\r\n\0')
file.close()

# Hostname
f = os.popen('/bin/hostname').readline()
host = f.replace("\n", "")

# CPU Temp
t = os.popen('vcgencmd measure_temp').readline()
temp = float(t.replace("temp=","").replace("'C\n",""))

# CPU frequency
f = os.popen('vcgencmd measure_clock arm').readline()
freq = float( f.replace("frequency(48)=", "").replace("\n", ""))/1000000

# CPU Voltage
v = os.popen('vcgencmd measure_volts').readline()
volt = float(v.replace("volt=","").replace("V\n",""))

# Timestamp
ts = int(time.time())

## Output as JSON
jsonData = json.dumps(OrderedDict([
    ("model", model),
    ("host", host),
    ("temp", temp),
    ("timestamp", ts),
    ("model", model),
    ("freq", freq),
    ("volt", volt)
]))
print(jsonData)

Well done !!

Just one last question. My program is a loop but I want node red to start it (via inject no problem) and I want to be able to stop it via node red too.

How can I do ?

From the help for node-red-node-daemon (Same for node-red-node-exec):

Setting msg.kill to a signal name (e.g. SIGINT, SIGHUP) will stop the process - but if the restart flag is set it will then auto restart.

Sending msg.start will also re-start the process. Additional arguments can be specified in msg.args.

Note: Some applications will automatically buffer lines of output. It is advisable to turn off this behaviour. For example, if running a Python app, the -u parameter will stop the output being buffered.

The way I handle this is to make the program read data once then exit (Like the example above). Then I can call it from inject/exec whenever I want the data.
I guess it's a difference between Node-red requests data when it needs it versus the program keeps feeding data and Node-red has to process it.

Thanks for your help !

For anyone interested here is the full code.

[{"id":"2ec2d7befa3c2dab","type":"inject","z":"b6155538.361f38","name":"start","props":[{"p":"start","v":"","vt":"date"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":110,"y":300,"wires":[["714f1c657f462976"]]},{"id":"714f1c657f462976","type":"exec","z":"b6155538.361f38","command":"python3 /home/pi/Documents/Programme/Power.py","addpay":"","append":"","useSpawn":"true","timer":"","oldrc":false,"name":"","x":410,"y":300,"wires":[["7560e22c.1f947c"],[],[]]},{"id":"3ab10.679814f0a","type":"inject","z":"b6155538.361f38","name":"kill","props":[{"p":"kill","v":"","vt":"date"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":110,"y":340,"wires":[["714f1c657f462976"]]},{"id":"7560e22c.1f947c","type":"json","z":"b6155538.361f38","name":"","property":"payload","action":"","pretty":false,"x":690,"y":300,"wires":[["4a60834c.34424c","1976216c.d88bef"]]},{"id":"4a60834c.34424c","type":"change","z":"b6155538.361f38","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"payload.Moteur1","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":880,"y":260,"wires":[["c0b3574c.d91388"]]},{"id":"1976216c.d88bef","type":"change","z":"b6155538.361f38","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"payload.Moteur2","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":880,"y":300,"wires":[["9fec52cc.bf781"]]},{"id":"c0b3574c.d91388","type":"ui_chart","z":"b6155538.361f38","name":"","group":"cdd79ca5.e959a","order":5,"width":0,"height":0,"label":"Moteur 1","chartType":"line","legend":"false","xformat":"HH:mm:ss","interpolate":"linear","nodata":"","dot":false,"ymin":"","ymax":"","removeOlder":"5","removeOlderPoints":"","removeOlderUnit":"60","cutout":0,"useOneColor":false,"useUTC":false,"colors":["#1f77b4","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"outputs":1,"useDifferentColor":false,"className":"","x":1040,"y":260,"wires":[[]]},{"id":"9fec52cc.bf781","type":"ui_chart","z":"b6155538.361f38","name":"","group":"cdd79ca5.e959a","order":6,"width":0,"height":0,"label":"Moteur 2","chartType":"line","legend":"false","xformat":"HH:mm:ss","interpolate":"linear","nodata":"","dot":false,"ymin":"","ymax":"","removeOlder":"5","removeOlderPoints":"","removeOlderUnit":"60","cutout":0,"useOneColor":false,"useUTC":false,"colors":["#1f77b4","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"outputs":1,"useDifferentColor":false,"className":"","x":1040,"y":300,"wires":[[]]},{"id":"cdd79ca5.e959a","type":"ui_group","name":"Commande","tab":"5aa580e8.1498","order":1,"disp":true,"width":"11","collapse":false,"className":""},{"id":"5aa580e8.1498","type":"ui_tab","name":"Commande","icon":"dashboard","order":1,"disabled":false,"hidden":false}]

POWER.py

# -*- coding: utf-8 -*-
import time
import json
import sys
import board
import busio
import digitalio
from digitalio import Direction, Pull
from adafruit_mcp230xx.mcp23017 import MCP23017
from collections import OrderedDict

import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)

from periphery import I2C
while 1==1:
	# Open i2c-1 controller
    i2c = I2C("/dev/i2c-1")

    msgs = [I2C.Message([0x61]), I2C.Message([0x00,0x00], read=True)]
    i2c.transfer(0x36, msgs)
    adc_value = (msgs[1].data[0] & 0x0F) <<8 | (msgs[1].data[1])
    adc_value_volt1=(adc_value*4.93/4096)
    msgs = [I2C.Message([0x63]), I2C.Message([0x00,0x00], read=True)]
    i2c.transfer(0x36, msgs)
    adc_value2 = (msgs[1].data[0] & 0x0F) <<8 | (msgs[1].data[1])
    adc_value_volt2=(adc_value2*4.93/4096)
    
    ## Output as JSON
    jsonData = json.dumps(OrderedDict([
        ("Moteur1", adc_value_volt1),
        ("Moteur2", adc_value_volt2),
    ]))
    print(jsonData)

    time.sleep(0.5)

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.