Quantcast
Channel: Raspberry Pi Forums
Viewing all articles
Browse latest Browse all 869

HATs and other add-ons • Problem when testing module DAC MCP4922 with Raspberry Pi

$
0
0
Greetings,
I'm encountering an issue while testing a custom-designed DAC module that utilizes an MCP4922 chip as its primary processor. The vendor provided C language test code for ESP32-S3, but I intend to test the module on a Raspberry Pi 3B+ using Python.
I've installed the Python-RPi-MCP4922 library and executed the test code, but the output voltage consistently remains at 0.
To investigate, I've:
Removed the MCP4922 chip from the module and connected it directly to a breadboard following the provided schematic. The chip functioned normally, with the output voltage fluctuating according to the code.
Reattached the MCP4922 chip to the module and ran the test code. The output voltage remained at 0.
Employed a VOM to directly measure the voltage at the VoutA pin of the MCP4922 on the module. The voltage at this pin also consistently remained at 0.
I suspect the issue may stem from:
Faulty DAC module hardware.
Modifications required in the Python code for compatibility with the module.
I kindly request your assistance in resolving this matter.
Thank you.

Additional Information:

Schematic of module DAC MCP4922: https://dientuagv.com/wp-content/upload ... apture.png

Python-RPi-MCP4922 Library: https://github.com/topics/mcp4922

Schematic connect with raspberry pi: https://github.com/mrwunderbar666/Pytho ... tch_bb.png, https://github.com/mrwunderbar666/Pytho ... tch_bb.png

C language test code for ESP32-S3:

Code:

//#define DA_SDI  51//#define DA_SCK  52//#define DA_CS   53#define DA_SDI  5#define DA_SCK  41#define DA_CS   42long int CNT_TIME1=0;static unsigned char buf[2];static unsigned char gain =2.5;static unsigned char buffered  = 1;static unsigned char shdn = 1;long int cnt_value=0; bool        usesHardwareReset = false;void convert_dac(unsigned char x){   // do chuc nang ghi dich 8 bit vao noi tiep ra song song     // do do vong for duoi se cho dich 8 lan de du 8 chan dau ra cho vdk int i,tam; for(i=0;i<8;i++) // 8 lan dich de co 8 bit {  tam=x;  tam=tam&0x80;  if(tam==0x80)  digitalWrite(DA_SDI, HIGH);  else   digitalWrite(DA_SDI, LOW);  x=x<<1;    // dich bit nhu sau   digitalWrite(DA_SCK, HIGH);;      digitalWrite(DA_SCK, LOW); }}void update_channels( unsigned int chA, unsigned int chB )  {  // write a value to channel A    buf[0] = (0 << 7) | (buffered << 6) | (gain << 5) | (shdn << 4) | (chA >> 8);    buf[1] = (chA & 0xff);     convert_dac( buf[0]);    convert_dac( buf[1]);    digitalWrite( DA_CS, HIGH);    digitalWrite(DA_CS, LOW);      // write a value to channel B  buf[0] = (1 << 7) | (buffered << 6) | (gain << 5) | (shdn << 4) | (chB >> 8);  buf[1] = (chB & 0xff); convert_dac( buf[0]);  convert_dac( buf[1]);   digitalWrite( DA_CS, HIGH);    digitalWrite(DA_CS, LOW);   // Update DAC output }void analogWrite(unsigned char odd, unsigned char buffered, unsigned char gain, unsigned char  active, unsigned int value)   {   unsigned char configBits  ;   unsigned char firstByte ;   unsigned char secondByte; configBits = odd << 3 | buffered << 2 | gain << 1 | active;  // Compose the first byte to send to the DAC:  // the 4 control bits, and the 4 most significant bits of the valuefirstByte= configBits << 4 | (value & 0xF00) >> 8; // Second byte is the lower 8 bits of the value secondByte = value & 0xFF;convert_dac(firstByte); convert_dac(secondByte);   digitalWrite( DA_CS, HIGH);    digitalWrite(DA_CS, LOW);  }void setup() {  // put your setup code here, to run once: pinMode(DA_SDI, OUTPUT);  pinMode(DA_SCK, OUTPUT);   pinMode(DA_CS, OUTPUT);}void loop() {  // put your main code here, to run repeatedly:  CNT_TIME1++;  switch(CNT_TIME1)  {    case 1000:cnt_value++;break;    case 2000: update_channels(cnt_value,cnt_value);break;    case 3000:CNT_TIME1=0;break;    }   if(cnt_value>4095) cnt_value=0;  // delay(1);}
Test code on Raspberry Pi 3B+ using Python:

Code:

#!/usr/bin/python"""Python Library for MCP4922 DAC using Raspberry Pi 3 Model B+2 Channels, 12 BitCurrently only supports Hardware SPIRequires: RPi.GPIO & spidev librariesWiring:MCP4922    =======>   Raspberry PiCS         ------->   GPIO08 Physical Pin 24 (SPI0 CE0) => Can be changedSDI        ------->   GPIO10 Physical Pin 19 (SPI0 MOSI) => cannot be changed in hardware SPI MODESCK        ------->   GPIO11 Physical Pin 23 (SPI0 SCLK) => cannot be changed in hardware SPI MODEMIT LicenseCopyright (c) 2017 mrwunderbar666Permission is hereby granted, free of charge, to any person obtaining a copyof this software and associated documentation files (the "Software"), to dealin the Software without restriction, including without limitation the rightsto use, copy, modify, merge, publish, distribute, sublicense, and/or sellcopies of the Software, and to permit persons to whom the Software isfurnished to do so, subject to the following conditions:The above copyright notice and this permission notice shall be included in allcopies or substantial portions of the Software.THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS ORIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THEAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHERLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THESOFTWARE."""import timeimport sysimport RPi.GPIO as GPIOimport spidevclass MCP4922(object):    """ Class for the Microchip MCP4922 digital to analog converter    """    spi = spidev.SpiDev()        def __init__(self,                 spibus=None,                 spidevice=None,                 cs=None                 ):        """ Initialize MCP4922 device with hardware SPI            Chipselect default value is BCM Pin 8 (Physical Pin: 24)            Select the bus and device number. Default values are:            Bus = 0 ; Device = 1            If you're not sure, just leave it default        """        mode = GPIO.getmode()        if mode == GPIO.BOARD:            default_cs = 24        elif mode == GPIO.BCM:            default_cs = 8        else:            raise ValueError(                "You haven't selected a GPIO Mode? Use: e.g. GPIO.setmode(GPIO.BCM)")        if cs is None:            self.cs = default_cs        else:            self.cs = cs        if spibus is None:            self.spibus = 0        else:            self.spibus = spibus        if spidevice is None:            self.spidevice = 1        else:            self.spidevice = spidevice        GPIO.setup(self.cs, GPIO.OUT)        GPIO.output(self.cs, 1)        # As soon as MCP4922 object is created spidev bus and device are opened        # otherwise causes memory leak and creates Errno 24        self.spi.open(self.spibus, self.spidevice)    def setVoltage(self, channel, value):        """        Regular setVoltage Function        Select your channel 0 or 1        Select Voltage value 0 to 4095        """        if channel == 0:            output = 0x3000 # 3 bit dau la bit dac biet de chon mode, 12 bit sau la du lieu         elif channel == 1:            output = 0xb000 # 3 bit dau la bit dac biet de chon mode, 12 bit sau la du lieu         else:            raise ValueError(                'MCP4922 Says: Wrong Channel Selected! Chose either 0 or 1!')        if value > 4095:            value = 4095        if value < 0:            value = 0        #self.spi.open(self.spibus, self.spidevice)        output |= value # gan data value cho output        buf0 = (output >> 8) & 0xff # tach 8 bit dau và sau        buf1 = output & 0xff        GPIO.output(self.cs, 0)        self.spi.writebytes([buf0, buf1])        GPIO.output(self.cs, 1)        #self.spi.close        return    def setVoltage_gain(self, channel, value):        """        The MCP4922 has the ability to output the double of the reference Voltage        Reference Voltage is measured by the MCP4922 at pin 13 (VrefA) for Channel A and pin 11 (VrefB) for Channel B        Note that the output voltage cannot exceed the supply voltage from pin 1 (VDD)        """        if channel == 0:            output = 0x1000 # 0111 0000 0000 0000        elif channel == 1:            output = 0x9000        else:            raise ValueError(                'MCP4922 Says: Wrong Channel Selected! Chose either 0 or 1!')        if value > 4095:            value = 4095        if value < 0:            value = 0        #self.spi.open(self.spibus, self.spidevice)        output |= value        buf0 = (output >> 8) & 0xff        buf1 = output & 0xff        GPIO.output(self.cs, 0)        self.spi.writebytes([buf0, buf1])        GPIO.output(self.cs, 1)        #self.spi.close        return    def setVoltage_buffered(self, channel, value):        """        Using the buffer feature of the MCP4922,        refer to the datasheet for details        """        if channel == 0:            output = 0x7000        elif channel == 1:            output = 0xF000        else:            raise ValueError(                'MCP4922 Says: Wrong Channel Selected! Chose either 0 or 1!')        if value > 4095:            value = 4095        if value < 0:            value = 0        #self.spi.open(self.spibus, self.spidevice)        output |= value        buf0 = (output >> 8) & 0xff        buf1 = output & 0xff        GPIO.output(self.cs, 0)        self.spi.writebytes([buf0, buf1])        GPIO.output(self.cs, 1)        #self.spi.close        return    def shutdown(self, channel):        """        Completely shutdown selected channel for power saving        Sets the output of selected channel to 0 and 500K Ohms.        Read Datasheet (SHDN) for details        """        if channel == 0:            output = 0x2000        elif channel == 1:            output = 0xA000        else:            raise ValueError(                'MCP4922 Says: Wrong Channel Selected! Chose either 0 or 1!')        #self.spi.open(self.spibus, self.spidevice)        buf0 = (output >> 8) & 0xff        buf1 = output & 0xff        GPIO.output(self.cs, 0)        self.spi.writebytes([buf0, buf1])        GPIO.output(self.cs, 1)        #self.spi.close        return    def close(self):        """        Closes the device        """        self.spi.close        return    def open(self):        """        Manually Open the device        """        self.spi.open(self.spibus, self.spidevice)        return    GPIO.setmode(GPIO.BCM)                 # use the Broadcom pin numberingGPIO.setwarnings(False)             # disable warningsif __name__ == '__main__':    dac = MCP4922()    try:        while True:            x = 0            for i in range(0, 100):                x = x + 40                dac.setVoltage(0, x)                dac.setVoltage(1, x)                print(x)                time.sleep(0.1)            for i in range(0, 100):                x = x - 40                dac.setVoltage(0, x)                dac.setVoltage(1, x)                print(x)                time.sleep(0.1)    except KeyboardInterrupt:   # Press CTRL C to exit program        dac.setVoltage(0, 0)        dac.setVoltage(1, 0)        dac.shutdown(0)        dac.shutdown(1)        GPIO.cleanup()        sys.exit(0)
Questions:

In your opinion, what could be causing the output voltage to remain at 0 consistently?

What modifications are necessary to the Python code for the module to function properly?

Do you have any other suggestions for troubleshooting this issue?

Thank you for your time and consideration.

Statistics: Posted by Lee123 — Tue Apr 02, 2024 3:21 pm



Viewing all articles
Browse latest Browse all 869

Trending Articles