Problems with more than one MCP3008

Hey all,

I have some problems with 3 MCP3008 adc's
Every time I try to address one of the MCPs, only the first one that I createt answers.
The others display the values from the first one.
If I only have one node in the flow the correct MCP answers.

I testet the setup with a python script to rule out hardware problems. That works fine.
I use a raspberry pi 2B,
# node-red-node-pi-mcp3008

I enabled the SPI interface with "dtoverlay=spi1-3cs"
spidev1.0 -->first MCP30008
spidev1.1 -->second MCP30008
spidev1.2 -->third MCP30008

Hello and welcome to the forum.

Without the same hardware, we wouldn't be able to test what you have... but even with, you would first need to supply the flow you are using so we could confim it is even setup properly.

3: Format your code/flows when posting

Presumably you have configured each to use the correct bus and device number. Do you try disconnecting the others and trying one at a time ?

Thank you for ansering.

Example one:
Only one MCP is connectet to CS0
On the first ADC Node I select CS0, and on the second ADC Node CS1
Now I get on the first Node the correct reading.
On the second Node I get a new reading from the MCP.
If i set all chip select to CS1, I get a "0" value on both ADC Nodes. ( because no second MCP is connected)

Example two:
Only one MCP is connectet to CS1
I get the same result as bevor but with CS0 and CS1 swapt.

It seams to me that the CS from the first node I createt will be used to select the CS for all other ADC Nodes

Here is my Node Red flow:

[{"id":"fa657575.0358f","type":"pimcp3008","z":"c5b27365.6557c","name":"","dev":"3008","pin":0,"dnum":"0","bus":"1","x":510,"y":80,"wires":[["357ac5e8.42bd3a"]]},{"id":"e208d23.3a62b3","type":"inject","z":"c5b27365.6557c","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":230,"y":80,"wires":[["fa657575.0358f"]]},{"id":"357ac5e8.42bd3a","type":"debug","z":"c5b27365.6557c","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":760,"y":80,"wires":[]},{"id":"eea3cda2.ccad88","type":"pimcp3008","z":"c5b27365.6557c","name":"","dev":"3008","pin":0,"dnum":"1","bus":"1","x":510,"y":120,"wires":[["df7ba289.d5d95"]]},{"id":"dd7ae34c.e13bb8","type":"inject","z":"c5b27365.6557c","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":230,"y":120,"wires":[["eea3cda2.ccad88"]]},{"id":"df7ba289.d5d95","type":"debug","z":"c5b27365.6557c","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":760,"y":120,"wires":[]}]

Node Red version [1.3.4 Maintenance Release]

Your flow indicates only two chips, not three... but each one is on the same SPI Bus (1)

Again, I don't have that chip in my random collection (that I am aware of) so just guessing here :stuck_out_tongue: So I will leave this one for the more knowledgeable node maintainer.

Without the chips it is hard to reproduce :sweat_smile:

To enable the third chip select in node red yot have to edit the pimcp3008.html file.
Add the third option on Line 40 so its look like that:

   <div class="form-row">
        <label for="node-input-dnum"><i class="fa fa-toggle-on"></i> Device ID</label>
        <select type="text" id="node-input-dnum" style="width:150px;">
          <option value=0>CE0</option>
          <option value=1>CE1</option>
          <option value=2>CE2</option>  
        </select>
    </div>

restart node red, and now you can select CS3 in the ADW Node.
I'm wasnt shure if that caused my problem, but it didnt work in the orginal version either.

So does that now work ok ? If we add that extra option ?

Not really,
With the extra option I can access the third MCP on CS2. But only if there is only one ADW node in the flow.

My problem starts when I am using 2 or 3 MCPs at the same time.
Are there any restrictions that only one MCP can be used?

Not that I’m aware of. As long as the CE is unique for each I would think it ought to work.

I found something interesting:
@Gunner It is possible to reproduce the bug without the Chips:
When the flow is running use the bash command:

 lsof /dev/spidev*

This will list all open devices. I expected an spidev1.x for each CS.
instead i get:

pi@testberrypi2:~ $ lsof /dev/spidev*
COMMAND   PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
node-red 1305   pi   22u   CHR  153,2      0t0  387 /dev/spidev1.0
node-red 1305   pi   23u   CHR  153,2      0t0  387 /dev/spidev1.0
node-red 1305   pi   24u   CHR  153,2      0t0  387 /dev/spidev1.0
node-red 1305   pi   25u   CHR  153,2      0t0  387 /dev/spidev1.0
node-red 1305   pi   26u   CHR  153,2      0t0  387 /dev/spidev1.0
node-red 1305   pi   27u   CHR  153,2      0t0  387 /dev/spidev1.0
node-red 1305   pi   29u   CHR  153,2      0t0  387 /dev/spidev1.0
node-red 1305   pi   30u   CHR  153,2      0t0  387 /dev/spidev1.0
pi@testberrypi2:~ $

I assume that every entry stands for an ADC input.
But then there should also appear lines like:

node-red 1305   pi   30u   CHR  153,1      0t0  386 /dev/spidev1.1

So the ohter SPI devices where never open to the MCPs.

Hello together,
I got the Problem fixed.

Here are the modified code:

pimcp3008.html

<!DOCTYPE html>
<script type="text/x-red" data-template-name="pimcp3008">
    <div class="form-row">
        <label for="node-input-dev"><i class="fa fa-server"></i> Device</label>
        <select type="text" id="node-input-dev" style="width:150px;">
            <option value="3008">mcp3008</option>
            <option value="3002">mcp3002</option>
            <option value="3004">mcp3004</option>
            <option value="3202">mcp3202</option>
            <option value="3204">mcp3204</option>
            <option value="3208">mcp3208</option>
            <option value="3304">mcp3304</option>
        </select>
    </div>
    <div class="form-row">
        <label for="node-input-pin"><i class="fa fa-map-pin"></i> Input pin</label>
        <select type="text" id="node-input-pin" style="width:150px;">
          <option value=0>A0</option>
          <option value=1>A1</option>
          <option value=2>A2</option>
          <option value=3>A3</option>
          <option value=4>A4</option>
          <option value=5>A5</option>
          <option value=6>A6</option>
          <option value=7>A7</option>
          <option value="M">set by msg.payload</option>
        </select>
    </div>
    <div class="form-row">
        <label for="node-input-dnum"><i class="fa fa-toggle-on"></i> Device ID</label>
        <select type="text" id="node-input-dnum" style="width:150px;">
          <option value=0>CE0</option>
          <option value=1>CE1</option>
	  <option value=2>CE2</option>	
        </select>
    </div>
    <div class="form-row">
        <label for="node-input-bus"><i class="fa fa-toggle-on"></i> SPI bus</label>
        <select type="text" id="node-input-bus" style="width:150px;">
          <option value=0>0</option>
          <option value=1>1</option>
        </select>
    </div>
    <div class="form-row">
        <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
        <input type="text" id="node-input-name" placeholder="Name"/>
    </div>
</script>

<script type="text/x-red" data-help-name="pimcp3008">
   <p>Reads from an MCP3xxx Series Analogue to Digital Converter (ADC) chip on the Pi SPI CE0 or CE1 connection,
   such as the rasp.io/analogzero.</p>
   <p>You can either set a channel in the edit dialogue, or you can set the <code>msg.payload</code>
   to select the channel dynamically. If so then the expected payload must be a value from 0 to 7.</p>
   <p>Outputs a numeric <code>msg.payload</code> with a range of 0 to 1023, representing 0V to 3.3V.</p>
   <p><i>Hint</i>: use a <code>range</code> node to re-scale the values to ones you want.</p>
   <p>Also sets <code>msg.topic</code> to <i>adc/{the pin number}</i></p>
   <p><b>Warning</b>: Input voltages must not exceed 3.3V</p>
   <p>The SPI bus must be enabled for this node to work. This can be achieved by using the
   advanced menu (option 9 A5) of the <b>raspi-config</b> utility.</p>
</script>

<script type="text/javascript">
    RED.nodes.registerType('pimcp3008',{
        category: 'Raspberry Pi',
        paletteLabel: 'A/D converter',
        color: "#c6dbef",
        defaults: {
            name: {value:""},
            dev: {value:"3008"},
            pin: {value:0, required:true},
            dnum: {value:0},
            bus: {value:0}
        },
        inputs: 1,
        outputs: 1,
        icon: "rpi.png",
        label: function() {
            return this.name || "mcp:"+this.dev+" "+" bus:"+this.bus+" CS:"+this.dnum+" pin:"+((this.pin==="M")?"":this.pin);
        },
        labelStyle: function() {
            return this.name?"node_label_italic":"";
        }
    });
</script>

pimcp3008.js


module.exports = function(RED) {
    "use strict";
    var fs2 = require('fs');
    var allOK = false;
    var mcpadc;
    // unlikely if not on a Pi
    try {
        var cpuinfo = fs2.readFileSync("/proc/cpuinfo").toString();
        if (cpuinfo.indexOf(": BCM") === -1) {
            RED.log.warn("Info : mcp3xxx : Not running on a Pi - Ignoring node");
        }
        else {
            mcpadc = require('mcp-spi-adc');
            allOK = true;
        }
    }
    catch(err) {
        RED.log.warn("Info : mcp3xxx : Not running on a Pi - Ignoring node");
    }

    //var mcp3xxx = [];

    function PiMcpNode(n) {
        RED.nodes.createNode(this,n);
        this.pin = n.pin || 0;
        this.interval = n.interval || 1000;
        this.dnum = parseInt(n.dnum || 0);
        this.bus = parseInt(n.bus || 0);
        this.dev = n.dev || "3008";
	this.fs = require('fs');
        this.mcp3xxx = [];
        var node = this;
        this.cb = function (err) { if (err) { node.error("Error: "+err); } };
        this.opt = { speedHz:20000, deviceNumber:node.dnum, busNumber:node.bus };
        var chans = parseInt(this.dev.substr(3));
	var node = this;

        if (allOK === true) {
            try {
                node.fs.statSync("/dev/spidev"+node.bus+"."+node.dnum);
                if (node.mcp3xxx.length === 0) {
                    for (var i=0; i<chans; i++) {
                        if (node.dev === "3002") { node.mcp3xxx.push(mcpadc.openMcp3002(i, node.opt, node.cb)); }
                        if (node.dev === "3004") { node.mcp3xxx.push(mcpadc.openMcp3004(i, node.opt, node.cb)); }
                        if (node.dev === "3008") { node.mcp3xxx.push(mcpadc.openMcp3008(i, node.opt, node.cb)); }
                        if (node.dev === "3202") { node.mcp3xxx.push(mcpadc.openMcp3202(i, node.opt, node.cb)); }
                        if (node.dev === "3204") { node.mcp3xxx.push(mcpadc.openMcp3204(i, node.opt, node.cb)); }
                        if (node.dev === "3208") { node.mcp3xxx.push(mcpadc.openMcp3208(i, node.opt, node.cb)); }
                        if (node.dev === "3304") { node.mcp3xxx.push(mcpadc.openMcp3304(i, node.opt, node.cb)); }
                    }
                }
                node.on("input", function(msg) {
                    var pin = null;
                    if (node.pin === "M") {
                        var pay = parseInt(msg.payload.toString());
                        if ((pay >= 0) && (pay < chans)) { pin = pay; }
                        else { node.warn("Payload needs to select channel 0 to "+(chans-1)); }
                    }
                    else { pin = parseInt(node.pin); }
                    if (pin !== null) {
                        node.mcp3xxx[pin].read(function (err, reading) {
                            if (err) { node.warn("Read error: "+err); }
                            else { node.send({payload:reading.rawValue, topic:"adc/"+pin}); }
                        });
                    }
                });
            }
            catch(err) {
                node.error("Error : Can't find SPI device - is SPI enabled in raspi-config ?"+ err);
            }

            node.on("close", function(done) {
                if (node.mcp3xxx.length !== 0) {
                    var j=0;
                    for (var i=0; i<chans; i++) {
                        node.mcp3xxx[i].close(function() { j += 1; if (j === chans) {done()} });
                    }
                    mcp3xxx = [];
                }
                else { done(); }
            });
        }
        else {
            node.status({text:"node inactive."})
        }
    }

    RED.nodes.registerType("pimcp3008",PiMcpNode);
}

Now all devises are showing up:

pi@testberrypi2:~/.node-red/node_modules/mcp-spi-adc $ lsof /dev/spidev*
COMMAND   PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
node-red 1886   pi   20u   CHR  153,2      0t0  387 /dev/spidev1.0
node-red 1886   pi   21u   CHR  153,2      0t0  387 /dev/spidev1.0
node-red 1886   pi   22u   CHR  153,2      0t0  387 /dev/spidev1.0
node-red 1886   pi   23u   CHR  153,2      0t0  387 /dev/spidev1.0
node-red 1886   pi   24u   CHR  153,2      0t0  387 /dev/spidev1.0
node-red 1886   pi   25u   CHR  153,2      0t0  387 /dev/spidev1.0
node-red 1886   pi   28u   CHR  153,2      0t0  387 /dev/spidev1.0
node-red 1886   pi   29u   CHR  153,2      0t0  387 /dev/spidev1.0
node-red 1886   pi   30u   CHR  153,0      0t0  385 /dev/spidev1.2
node-red 1886   pi   31u   CHR  153,0      0t0  385 /dev/spidev1.2
node-red 1886   pi   32u   CHR  153,0      0t0  385 /dev/spidev1.2
node-red 1886   pi   33u   CHR  153,0      0t0  385 /dev/spidev1.2
node-red 1886   pi   34u   CHR  153,0      0t0  385 /dev/spidev1.2
node-red 1886   pi   35u   CHR  153,0      0t0  385 /dev/spidev1.2
node-red 1886   pi   36u   CHR  153,0      0t0  385 /dev/spidev1.2
node-red 1886   pi   37u   CHR  153,0      0t0  385 /dev/spidev1.2
node-red 1886   pi   38u   CHR  153,1      0t0  386 /dev/spidev1.1
node-red 1886   pi   39u   CHR  153,1      0t0  386 /dev/spidev1.1
node-red 1886   pi   40u   CHR  153,1      0t0  386 /dev/spidev1.1
node-red 1886   pi   41u   CHR  153,1      0t0  386 /dev/spidev1.1
node-red 1886   pi   42u   CHR  153,1      0t0  386 /dev/spidev1.1
node-red 1886   pi   43u   CHR  153,1      0t0  386 /dev/spidev1.1
node-red 1886   pi   44u   CHR  153,1      0t0  386 /dev/spidev1.1
node-red 1886   pi   45u   CHR  153,1      0t0  386 /dev/spidev1.1
pi@testberrypi2:~/.node-red/node_modules/mcp-spi-adc $
1 Like

Do you fancy raising a pull request so we can fix the node easily. (Otherwise it’ll have to wait until I’m back from vacation)

So the pull request is created.

I hope I done it right, this was my first request on github. :laughing:

1 Like

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