MCP3002 not displaying voltage jumps

Can anyone help me. I am using the sample program for the MCP3002 to display voltage. It only shows either "0" or 79.99 on both channels.
The following is the code I am using.


#include "simpletools.h" // Include simpletools
#include "adcDCpropab.h" // Include adcDCpropab

int main() // Main function
{
adc_init(8, 9, 10, 11); // CS=Pin1, SCL=Pin7, DO=Pin6, DI=Pin5

float v0, v1; // Voltage variables

while(1) // Loop repeats indefinitely
{
v0 = adc_volts(0); // Check A/D 0
v1 = adc_volts(1); // Check A/D 1

putChar(HOME); // Cursor -> top-left "home"
print("A/D0 = %f V%c\n", v0, CLREOL); // Display volts
print("A/D1 = %f V%c\n", v1, CLREOL); // Display volts

pause(100); // Wait 1/10 s
}
}


Anyone's assistance will be appreciated.
Dave

Comments

  • yisiguroyisiguro Posts: 25
    edited 2019-04-07 - 01:07:23
    Is a comment below a help here ?

    http://forums.parallax.com/discussion/comment/1221392/#Comment_1221392
    The adcDCpropab.h is designed to communicate with the ADC on the Propeller Activity board which is a "ADC124SO21"
  • I wrote a library function for MCP3202 chip but it is easy enough to just read the values from the chip.

    Here is the code to read MCP3202 chip:
    // millivolts times 1000
    int mcp3202_read(int R)
    {
      unsigned int i;
      
      if (R == 0)
        i = 0xd; //1101
      else
        i = 0xf; //1111
    
      low(mcpCS);
      shift_out(mcpDIN, mcpCLK, MSBFIRST, 4, i);
      i = shift_in(mcpDOUT, mcpCLK,  MSBPOST, 12);
      high(mcpCS);
      return i;
    }
      
    int mcp3202_volts(int R)
    {
      int i;
      
      i = mcp3202_read(R);
      i = i * 1000;
      i = i / 1226;
      return i;
    }
    

    Since this chip has two ADC lines the variable R is really the channel you want to read.

    Also the MCP3002 is only a 10 bit resolution chip so you need to change the 12 above to 10.

    Mike
  • Mike, I had to add code, your code was incomplete. But I am not getting anything on my display

    // millivolts times 1000
    #include "simpletools.h" // Include simpletools

    #include <propeller.h>

    #include "adcDCpropab.h" // Include adcDCpropab
    const int ON = 254;
    const int CLR = 1;
    int main()
    { // Main function
    int mcp3202_read(int R)
    {

    int mcpCS = input(8);
    int mcpDIN = input(11);
    int mcpCLK = input(7);
    int mcpDOUT = output(6);
    unsigned int i;

    if (R == 0)
    i = 0xd; //1101
    else
    i = 0xf; //1111

    low(mcpCS);
    shift_out(mcpDIN, mcpCLK, MSBFIRST, 4, i);
    i = shift_in(mcpDOUT, mcpCLK, MSBPOST, 10);
    high(mcpCS);
    return i;

    }
    int mcp3202_volts(int R)
    {
    int i;

    i = mcp3202_read(R);
    i = i * 1000;
    i = i / 1226;
    pause(100);
    serial *lcd = serial_open(12, 12, 0, 9600); //Pin12 out,pin12 in,data bits 0,baud rate 9600
    writeChar(lcd, ON);
    writeChar(lcd, CLR);
    dprint(lcd,"Volts %d", i); //display volts
    pause(100);
    return i;
    }
    }

    Your assistance will be appreciated.
    Dave
  • PublisonPublison Posts: 10,960
    edited 2019-04-06 - 17:36:37
    As per the second post, do you really want to include "adcDCpropab.h"? That's a completely different ADC. I many not even affect your program.

    Also when posting, please use coding brackets, (the big C in the editor). This will show code as it is supposed to be viewed. When the "Code/code) shows up copy and paste your code between the brackets.
    Infernal Machine
  • Here some code to display the voltage on the LCD display.

    I used two resistors 10K each with 5 volts. This would result in a voltage of 2.5 volts

    Attached is a picture of the setup with an MCP3204 chip connect between the two 10k resistors with a voltage reading of 2.5
    #include "simpletools.h"
    
    // pre define function
    int readMCP3204(char);
    int readMCP3002(char);
    
    const char ON = 22;
    const char CLR = 12;
    const char H = 128;
    const char L2 = 192;
    
    #define BLTON 17
    
    #define CLK  2
    #define DOUT 3
    #define DIN  4
    #define CS   5
    
    // high bit is start bit
    #define CHANNEL 0x18
    #define TWOCHANNEL 0x06
    
    
    int i;
    serial *lcd;
    float v;
    
    int main()
    {
      lcd = serial_open(8, 8, 0, 19200); //Pin12 out,pin12 in,data bits 0,baud rate 9600
      
      writeChar(lcd, ON);
      writeChar(lcd, BLTON);
      
      input(DOUT);
      
      low(CS);
      high(CS);
      
    
      while (1)
      {
        i = readMCP3204(1);
        print("Value: %d\n", i);
        v = i;
        v = v / 4096 * 5; // digital output code =(4096 * Vin) / Vdd
        dprint(lcd, "%cVolts: %f", CLR, v);
        pause(1000);
      }      
    }
    
    // c = channel pin
    // rotate 1 to set conversion start
    int readMCP3204(char c)
    {
      short v;
      
      low(CS);
      v = (CHANNEL + c) << 1;
      shift_out(DIN, CLK, MSBFIRST, 6, v);
      v = shift_in(DOUT, CLK, MSBPOST, 12);
      high(CS);
      return v;
    }
    
    int readMCP3002(char c)
    {
      short v;
      
      low(CS);
      v = (TWOCHANNEL + c) << 1;
      v = v | 0x01; // MSBF bit value
      shift_out(DIN, CLK, MSBFIRST, 4, v);
      v = shift_in(DOUT, CLK, MSBPOST, 10);
      high(CS);
      return v;
    }
    

    This code will not work for MCP3002 as it only has 2 inputs and require a MSBF bit. The readMCP3002 function should work instead. Also the reading changes as it is only 10 bits so the new formula is: reading = (1024 X Vin) / Vdd

    Solving for Vin would be:

    v = v / 1024 * 5


    Mike
    2560 x 1440 - 1M
  • Mike, it is kind of working, but what is happening, like on my display, it will read up to 400 then it starts over again and does this for 3 times. It does this with the terminal view except it is a 4 digit number. I made a few changes to work with my setup.

    #include "simpletools.h"

    // pre define function
    int readMCP3204(char);
    int readMCP3002(char);

    const char ON = 254;
    const char CLR = 1;
    const char H = 128;
    const char L2 = 192;

    #define BLTON 17

    #define CLK 9
    #define DOUT 10
    #define DIN 11
    #define CS 8

    // high bit is start bit
    #define CHANNEL 0x18
    #define TWOCHANNEL 0x06

    int n;
    int i;
    serial *lcd;
    float v;

    int main()
    {

    input(DOUT);

    while (1)
    {
    i = readMCP3204(1);
    print("Value: %d\n", i);

    lcd = serial_open(12, 12, 0, 9600); //Pin12 out,pin12 in,data bits 0,baud rate 9600
    writeChar(lcd, ON);
    writeChar(lcd, CLR);
    i = readMCP3204(1);
    n = i;
    n = n/10;
    dprint(lcd, "Volts: %d",n );
    pause(1000);
    }
    }

    //c = channel pin
    //rotate 1 to set conversion start
    int readMCP3204(char c)
    {
    short v;

    low(CS);
    v = (CHANNEL + c) << 1;
    shift_out(DIN, CLK, MSBFIRST, 6, v);
    v = shift_in(DOUT, CLK, MSBPOST, 12);
    high(CS);
    return v;
    }

    int readMCP3002(char c)
    {
    short v;

    low(CS);
    v = (TWOCHANNEL + c) << 1;
    v = v | 0x01; // MSBF bit value
    shift_out(DIN, CLK, MSBFIRST, 4, v);
    v = shift_in(DOUT, CLK, MSBPOST, 10);
    high(CS);
    return v;
    }


    Dave
  • You have to use the MCP3002 function and not the MCP3204. My unit is a 12 bit version of the 3002 which is a 10 bit version. This effects the value returned by the device.

    MCP3204 can return a value between 0 and 4096 (2^12)
    MCP3002 can return a value between 0 and 1024 (2^10)

    So the shift function it trying to return 12 bits instead of 10 for your unit. Also MCP3204 has a different select sequence so the bits returned will be shifted.

    Using the MCP3002 function it should work correctly.
    int main()
    {
      lcd = serial_open(12, 12, 0, 9600); //Pin12 out,pin12 in,data bits 0,baud rate 9600
      
      writeChar(lcd, ON);
      writeChar(lcd, BLTON);
      
      input(DOUT);
      
      low(CS);
      high(CS);
      
    
      while (1)
      {
        i = readMCP3002(0);
        print("Value: %d\n", i);
        writeChar(lcd, ON);
        writeChar(lcd, CLR);
        i = readMCP3002(0);
        n = i;
        n = n / 10;
        dprint(lcd, "Volts: %d", n);
        pause(1000);
      }      
    }
    

    Also you defined n as an integer so there is no decimal digits. So 1/10 = 0 where as if you use float it would return 0.1 as a value.

    Mike
Sign In or Register to comment.