mike_3rdgear
Posts: 1
Joined: Thu Jul 12, 2018 7:44 pm

pi4j implementation for SPI communications with MCP3008 reading zeros

Thu Jul 12, 2018 8:09 pm

I have hardwired a MCP3008 IC into the SPI input on a Raspberry Pi3.

MCP3008 is wired as follows:

pin 10 (CS) to Pi GPIO_10 (pin 24) this is CE0

pin 11 (Din) to Pi GPIO_12 (pin 19) this is MOSI

pin 12 (Dout) to Pi GPIO_13 (pin 21) this is MISO

pin 13 (CLK) to Pi GPIO_14 (pin 23) this is SCLK

I am using a single TMP36 wired into channel 0, pin 1 of the MCP3008.

When I measure the voltage of the TMP36 output it is correlating to the measured surface temperature of the board it is mounted to, which is approximately 23 degrees celsius. For those interested, I am using a Fluke 62 MAX+ IR thermometer to take the measurement.

My problem is twofold:

1) I read nothing but zero in my java program, and in a python script I wrote for comparison. Here is the output I get when I make a HTTP GET request to the resource.

Code: Select all

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<gpioRepresentation>
    <garageDoorFeedbackState>LOW</garageDoorFeedbackState>
    <zoneOneState>LOW</zoneOneState>
    <zoneTwoState>LOW</zoneTwoState>
    <zoneThreeState>LOW</zoneThreeState>
    <garageDoorRelayState>LOW</garageDoorRelayState>
    <panelTemperature>0.0</panelTemperature>
    <zoneOneRelayState>LOW</zoneOneRelayState>
    <zoneThreeRelayState>LOW</zoneThreeRelayState>
    <zoneTwoRelayState>LOW</zoneTwoRelayState>
</gpioRepresentation>
2) Why are both CE0 and CE1 measuring 3.3Vdc?

My understanding of SPI is that the active channel must have its corresponding chip select logic level LOW or 0Vdc. So why is it high? How can I drive it low using the pi4j library or in python?

Here is the class with the code I wrote for this. I have included all imports, fields, and the constructor. I have omitted getters and setters as they take too much space and aren't relevant to this.

Code: Select all

...

import com.pi4j.gpio.extension.base.AdcGpioProvider;
import com.pi4j.gpio.extension.mcp.MCP3008GpioProvider;
import com.pi4j.gpio.extension.mcp.MCP3008Pin;
import com.pi4j.io.gpio.GpioController;
import com.pi4j.io.gpio.GpioFactory;
import com.pi4j.io.gpio.GpioPinAnalogInput;
import com.pi4j.io.gpio.GpioPinDigitalInput;
import com.pi4j.io.gpio.GpioPinDigitalOutput;
import com.pi4j.io.gpio.PinPullResistance;
import com.pi4j.io.gpio.PinState;
import com.pi4j.io.gpio.RaspiPin;
import com.pi4j.io.gpio.event.GpioPinAnalogValueChangeEvent;
import com.pi4j.io.gpio.event.GpioPinDigitalStateChangeEvent;
import com.pi4j.io.gpio.event.GpioPinListenerAnalog;
import com.pi4j.io.gpio.event.GpioPinListenerDigital;
import com.pi4j.io.spi.SpiChannel;
import com.pi4j.io.spi.SpiMode;

...

/**
 * Class that models the physical Raspberry Pi resources and represents them in XML.
 * Access methods to read and write physical I/O state are synchronized to 
 * maintain consistent state of the GPIO when multiple users are accessing
 * the controls.
 * Only one object of this class is to ever exist, as it is a representation
 * of this physical real world device that it resides on.
 */
@XmlRootElement
public class GpioRepresentation implements GpioSubject, EventSubject 
{
    private static GpioRepresentation gpioRepresentation = null;
    private GpioObserver observingResource;
    private EventObserver eventObserver;
    private final GpioController gpio;
    ...
    private final AdcGpioProvider provider;
    private final GpioPinAnalogInput rawInput;

    ...

    @XmlTransient
    private double panelTemperature;

    private GpioRepresentation() throws IOException
    {
        //get instance of gpio factory object
        gpio = GpioFactory.getInstance();

        ...

        // Create custom MCP3008 analog gpio provider
        provider = new MCP3008GpioProvider(SpiChannel.CS0, SpiMode.MODE_0);

        // Provision gpio analog input pins for all channels of the MCP3008.
        rawInput= gpio.provisionAnalogInputPin(provider, MCP3008Pin.CH0, "MyAnalogInput-CH0");

        // Define the amount that the ADC input conversion value must change before
        // a 'GpioPinAnalogValueChangeEvent' is raised.  This is used to prevent unnecessary
        // event dispatching for an analog input that may have an acceptable or expected
        // range of value drift.
        provider.setEventThreshold(100, rawInput);

        // Set the background monitoring interval timer for the underlying framework to
        // interrogate the ADC chip for input conversion values.  
        provider.setMonitorInterval(250);

        // Create an analog pin value change listener
        GpioPinListenerAnalog aDClistener = new GpioPinListenerAnalog()
        {
            public void handleGpioPinAnalogValueChangeEvent(GpioPinAnalogValueChangeEvent event)
            {
                // get RAW value
                double value = event.getValue();

                //calculate the temperature
                calculateTemperature(value);

            }
        };

        // Register the gpio analog input listener for input
        gpio.addListener(aDClistener, rawInput);

    }

    public void calculateTemperature(double raw)
    {
        double millivolts = raw * ( 3300.0 / 1023.0 );
        panelTemperature = ((millivolts - 500.0) / 10.0);
    }

    @XmlElement
    public synchronized double getPanelTemperature()
    {
        return panelTemperature;
    }

    ... (other methods omitted)
}
As an FYI, SPI has been configured/enabled on my Pi. I am using Ubuntu Mate as my OS.

Please note that in the attached pictures, I have corrected the connections (reversed) for MOSI and MISO, as these were incorrect.
Attachments
circuit diagram.png
circuit diagram.png (151.41 KiB) Viewed 422 times

User avatar
DougieLawson
Posts: 33850
Joined: Sun Jun 16, 2013 11:19 pm
Location: Basingstoke, UK
Contact: Website

Re: pi4j implementation for SPI communications with MCP3008 reading zeros

Fri Jul 13, 2018 6:03 pm

Here's my sample stand-alone Java program (using the Pi4J snapshot).

Code: Select all

import com.pi4j.gpio.extension.base.AdcGpioProvider;
import com.pi4j.gpio.extension.mcp.MCP3008GpioProvider;
import com.pi4j.gpio.extension.mcp.MCP3008Pin;
import com.pi4j.io.gpio.GpioController;
import com.pi4j.io.gpio.GpioFactory;
import com.pi4j.io.gpio.GpioPinAnalogInput;
import com.pi4j.io.gpio.event.GpioPinAnalogValueChangeEvent;
import com.pi4j.io.gpio.event.GpioPinListenerAnalog;
import com.pi4j.io.spi.SpiChannel;

public class readTmp36 {

    private static double milliVtoDegC (double milliV) {
        double tempDegC = (milliV - 0.5) /10;
        return tempDegC;

    }

    public static void main(String args[]) throws Exception {

        System.out.println("<--Pi4J--> TMP36 ... started.");

        final GpioController gpio = GpioFactory.getInstance();
        final AdcGpioProvider provider = new MCP3008GpioProvider(SpiChannel.CS0);
        final GpioPinAnalogInput inputs[] = {
                gpio.provisionAnalogInputPin(provider, MCP3008Pin.CH0, "TMP36-CH0"),
        };


        provider.setEventThreshold(100, inputs);
        provider.setMonitorInterval(250); // milliseconds

        for(GpioPinAnalogInput input : inputs){
            System.out.println("<INITIAL VALUE> [" + input.getName() + "] : RAW VALUE = " + milliVtoDegC(input.getValue()));
        }

        GpioPinListenerAnalog listener = new GpioPinListenerAnalog()
        {
            @Override
            public void handleGpioPinAnalogValueChangeEvent(GpioPinAnalogValueChangeEvent event)
            {
                double value = milliVtoDegC(event.getValue());

                System.out.println("<CHANGED VALUE> [" + event.getPin().getName() + "] : RAW VALUE = " + value);
            }
        };

        gpio.addListener(listener, inputs);

        for (int count = 0; count < 600; count++) {
            Thread.sleep(1000);
        }

                gpio.shutdown();

        System.out.println("Exiting TMP36");
    }
}
The value returned by Pi4J is already corrected for reference voltage and the 10-bit ADC. So the only maths I'm doing is to convert the returned value into °C.
Microprocessor, Raspberry Pi & Arduino Hacker
Mainframe database troubleshooter
MQTT Evangelist
Twitter: @DougieLawson

2012-18: 1B*5, 2B*2, B+, A+, Z, ZW, 3Bs*3, 3B+

Any DMs sent on Twitter will be answered next month.

Return to “Java”

Who is online

Users browsing this forum: No registered users and 2 guests