1

I am using raspberry pi 3. I am trying to run the AC induction motor for that I want an analog pin. In raspberry pi model doesn't have an analog pin. All pins are digital IO pins.

So I have tried MCP 4725 DAC. Below I have mentioned which library I am using and what I have tried. This is new for me, I am facing some difficulties It might be experiance issue also.

I need a help to solve this issue. Sorry for my poor english, I hope you can understand the problem listed here.

mcp4725.h

#ifdef __cplusplus
extern "C" {
#endif

#define WRITEDAC 0x40
#define WRITEDACEEPROM 0x60
#define MCP4725 0x62

void setVoltage(int fd, int voltage, int persist);
extern int mcp4725Setup(int pinBase, int id);

#ifdef __cplusplus
}
#endif

mcp4725.cpp

#include <wiringPi.h>
#include <wiringPiI2C.h>

#include "mcp4725.h"

/* MCP4725 analogWrite function:
 *    value is 12bit data to be writen.
 *    pin is a mask for write type:
 *    pinBase + 0 - DAC standard
 *    pinBase + 1 - EEROM write DAC
*===================================*/

static void myAnalogWrite(struct wiringPiNodeStruct *node, int pin, int value) {
  // 2 byte array to hold 12bit data chunks
  int data[2];
  // pin is a mask for DAC set to EEROM
  int persist = pin - node->pinBase;

  // limit check value
  value = (value > 4095) ? 4095 : value;

  // MCP4725 expects a 12bit data stream in two bytes (2nd & 3rd of transmission)
  data[0] = (value >> 8) & 0xFF; // [0 0 0 0 D12 D11 D10 D9 D8] (first bits are modes for our use 0 is fine)
  data[1] = value; // [D7 D6 D5 D4 D3 D2 D1 D0]

  // 1st byte is the register
  if (persist) {
    wiringPiI2CWrite(node->fd, WRITEDACEEPROM);
  } else {
    wiringPiI2CWrite(node->fd, WRITEDAC);
  }

  // send our data using the register parameter as our first data byte
  // this ensures the data stream is as the MCP4725 expects
  wiringPiI2CWriteReg8(node->fd, data[0], data[1]);
}

/* MCP4725 DAC setup:
 *    create MC4725 device.
 *    id is the address of the chip (0x62 default)
*===============================================*/

int mcp4725Setup(const int pinBase, int id) {
  struct wiringPiNodeStruct *node;

  node = wiringPiNewNode(pinBase,2);

  node->fd = wiringPiI2CSetup(id);
  node->analogWrite = myAnalogWrite;

  if (node->fd < 0) {
    return -1;
  } else {
    return 0;
  }
}

Project (on of the thread (so main not using))

#include "mcp4725.h"

int output_dac, i_dac;

using namespace std;


Motion::Motion()
{
      mcp4725Setup(100,WRITEDACEEPROM); // 0x60 address 
}

Motion::~Motion()
{
    cout<<"Motion Destroyed"<< endl;
}

void Motion::move_Motion()
{
    output_dac = 2000; // 200 = 0.200v , 1000 = 1.124v, 2000 = 2.117v(max)

    analogWrite(100, output_dac);
}


void Motion::stop_Motion()
{
    output_dac = 0;  // 0=0v

    analogWrite(0, output_dac);
}

If I keep 0 then it is stopping properly. similar way I want to increase and decrease voltage also.

If I increase the voltage range above 2000 it is not working. The maximum voltage that is going up to 2.1v but I want 5v. I have tried 8000 but still it is 2.117v.

Is there any mistake in the code. Can you help me to fix this issue?

2 Answers 2

0

The MCP4725 is a 12-Bit Digital-to-Analog Converter with EEPROM Memory. You can create a simple setup with the wiringpi library, the wiringpi library has analogRead (int pin); function but you can't use here.

This returns the value read on the supplied analog input pin. You will need to register additional analog modules to enable this function for devices such as the Gertboard, quick2Wire analog board, etc.

It’s not the fastest of systems – the maximum sampling speed is going to be about 2000 samples/second and output update speed about double that. Not quite good enough for audio at those speeds but should be more than adequate to read various analog sensors and so on.

I have no experience yet with that library (MCP4725), but I have tried wiringpiI2C library it will work fine.

void Motion::move_Motion()
{
  value= wiringPiI2CWriteReg16(id, 0x40, (255 & 0xfff) );
}


void Motion::stop_Motion()
{
  value= wiringPiI2CWriteReg16(id, 0x40, (0 & 0xfff) );
}

It's time to check the result.

1
  • Thanks for your answer. It is working fine. I have checked. If I keep 0 it is in stop condition. If I increase or decrease the value according to that voltage values are changing.
    – uvan
    Commented Apr 30, 2018 at 12:41
1

I am interested to know more. But don't expect too much, because I have never used MCP4725 DAC before. Neither have I used any induction motor. I once used RPi python to play with another I2C DAC called pcf8591 which is easier because there is no EEPROM with it.

I am a hobbyist programmer with about 200 hours Arduino C++ DIY project experience, so I can read your C++ program, but I found it a bit complicated. I think the first step for me is to read the datasheet and understand the operation.

So I downloaded the datasheet and skimmed through it. I am now making a testing plan and you may like to give me any advice on this plan.

First I would like to tell you my general principles and approaches.

  1. Make it as simple as possible, but not simpler.

I read that you don't need to use the eeprom to do DAC. You just give the command and input code to the data register and do the DAC. In short, we will start without the EEPROM.

I also read that the EEPROM has a default input code which is at the middle point of the range. So if we use 5V0, we will get 2V5 output.

  1. Use functions whenever possible. It is easy to convert functions to objects, but not the other way round.

  2. Do not use wiringPi for now. Python can just read and write to MCP with one write and one read I2C command. So wiring Pi is sort of over kill. I know python can use wiringPi. But I am not sure if Python wiring pi is 100% compatible with C++ wiringPi. So I think it is easy to first play with Python, then C++, then wiring Pi.

  3. Time for me to go to bed. Sorry for misspellings etc. See you tomorrow. ZZZ.


Now I have written my first program to test MCP4725. This is the first working version. It can set values of zero, one third, one quarter, one half, full scale etc. Next step is to add the read/write EEPROM part. My plan is to use the DAC to control the volume of an audio power amplifier PAM8610

# *** dac01.006.1054 tlfong01 2018may02hkt1332 ***
#!/usr/bin/python3

from   decimal import *
import buzzer01 as buzzer
import timer01 as timer
import menu01 as menu
import digiout01 as digiout
import fprint01 as fprint
import sys01 as sys
import i2c01 as i2c
import demux01 as demux

# *** MCP4725 DAC Config ***

# ***Init config ***

initI2cPortNum     = 0
initI2cDemuxChNum  = 1
initDeviceNum      = 0
initDeviceBaseAddr = 0x62
initDeviceSubAddr  = 0x0
initModuleName     = 'ModuleDac00' 

# *** Work config ***

i2cPortNum       = initI2cPortNum
deviceNum        = initDeviceNum
deviceBaseAddr   = initDeviceBaseAddr
deviceSubAddr    = initDeviceSubAddr
deviceAddr       = deviceBaseAddr | deviceSubAddr
moduleName       = initModuleName

# Init config function ***

# *** Device Control byte ***

controlByte = {
        '0x01'                                  : 0x01,
        '0x55'                                  : 0x55,
        '0x66'                                  : 0x66,
        '0xaa'                                  : 0xaa,
        '0x0f'                                  : 0x0f,
        '0xf0'                                  : 0xf0,     
        }


# *** 9. Config Module/Device Group / Device Functions ***

def selectI2cDemuxCh(i2cDemuxChNum):
    fprint.printBeginExecuteFunction334()
    i2c.resetDemuxChAllHighActive()
    i2c.selectDemuxChHighActive(i2cDemuxChNum)
    fprint.printBeginExecuteFunction334()
    return

# *** Test Function ***

def writeDeviceOneByte(i2cPortNum, mcp4725DeviceAddr, writeByte):
    fprint.printBeginExecuteFunction334()
    i2c.writeDeviceOneByte(i2cPortNum, mcp4725DeviceAddr, writeByte)
    fprint.printEndExecuteFunction334()
    return

def writeDeviceTwoBytes(i2cPortNum, deviceAddr, dataByte1, dataByte2):
    i2c.writeDeviceTwoBytes(i2cPortNum, deviceAddr, dataByte1, dataByte2)
    return

def readDeviceOneByte(i2cPortNum, mcp4725DeviceAddr):
    readByte = i2c.readDeviceOneByte(i2cPortNum, mcp4725DeviceAddr)
    return readByte


# *** Input codes ***

vddMinusOneLsb = 0xfff
oneLsb         = 0x001
oneThirdInputCode = 0x555
zero           = 0x000
factoryDefault = 0x200
halfVdd        = 0x200

inputCodeZero       = 0x0
inputCodeMin        = 0x1
inputCodeFull        = 0x1000 - 1
inputCodeHalf        = 0x1000 >> 1
inputCodeOneQuarter = 0x1000 >> 2       # 5V34 / 4 = 1V34
inputCodeOneEighth  = 0x1000 >> 3
inputCodeOneThird   = 0x0555            # 5V34 / 3 = 1V78
testInputCode       = 0x345


# *** Write Command Type (3 bits) ***
writefastModeC2C1C0        = 0b000
writeDacRegC2C1C0          = 0b010
writeDacRegAndEepromC2C1C0 = 0b011

# *** WriteCommd Type (2 bits) ***
writeFastModeC2C1          = 0b00
writeDacRegC2C1            = 0b01

# *** General Call Bytes ***

generalCallFirstByte        = 0x00
generalCallResetSecondByte  = 0x60
generalCallWakeupSecondByte = 0x90

# *** High Speed (HS 3.4MBit/s) Mode ***

highSpeedModeByte           = 0x04

# *** Change DAC code in Fast Mode ***

writeAddr0x62FirstByte     = 0x62
writeAddr0x31FirstByte     = 0x63

# *** Read Reg and Eeprom data ***

readAddr0x62FirstByte      = 0x62
readAddr0x62FirstByte      = 0x62

# *** Power Down Bits ***

powerDownNormalModePd1Pd0 = 0b00
powerDown1kPd1Pd0         = 0b01
powerDowon100KPd1Pd0      = 0b10
powerDoan500KPd1Pd0       = 0b11

fastModeWordOneThirdInputCode    = (writeFastModeC2C1 << 14) | oneThirdInputCode
fastModeWordOneThirdInputCodeLsbByte    = fastModeWordOneThirdInputCode & 0x0f
fastModeWordOneThirdInputCodeMsbByte    = fastModeWordOneThirdInputCode & 0xf0
writeDacRegWordOneThirdInputCode = (writeDacRegC2C1C0 << 21)  | oneThirdInputCode

def resetDevice(i2cPortNum, deviceBaseAddr, deviceSubAddr):
    fprint.printBeginExecuteFunction334()
    deviceAddr = deviceBaseAddr | deviceSubAddr
    generalCallByte1 = 0x00
    resetByte = 0x06
    generalCallByte2 = resetByte
    i2c.writeDeviceOneByte
    fprint.printEndExecuteFunction334()
    return

def wakeupDevice(i2cPortNum, deviceBaseAddr, deviceSubAddr):
    fprint.printBeginExecuteFunction334()
    deviceAddr = deviceBaseAddr | deviceSubAddr
    generalCallByte1 = 0x00
    wakeupByte = 0x09
    generalCallByte2 = wakeupByte
    i2c.writeDeviceOneByte
    fprint.printEndExecuteFunction334()
    return

def setVolt(i2cPortNum, deviceBaseAddr, deviceSubAddr, inputCode):
    fprint.printBeginExecuteFunction334()

    inputCodeHighByte = (inputCode & 0x0f00) >> 8
    inputCodeLowByte  = inputCode & 0x0ff
    fprint.printTitleNumNoNewLine('inputCodeH', 5, 32, hex(inputCode))
    fprint.printTitleNumNoNewLine('inputCodeHighByte', 5, 32, fprint.convertNumToFourChaarPadString(inputCodeHighByte))
    fprint.printTitleNumNoNewLine('inputCodeLowByte', 5, 32, fprint.convertNumToFourChaarPadString(inputCodeLowByte))

    deviceAddr = deviceBaseAddr | deviceSubAddr
    fprint.printTitleNumNoNewLine('deviceBaseAddr', 5, 32, fprint.convertNumToFourChaarPadString(deviceBaseAddr))
    fprint.printTitleNumNoNewLine('deviceSubAddr', 5, 32, fprint.convertNumToFourChaarPadString(deviceSubAddr))
    fprint.printTitleNumNoNewLine('deviceAdr', 5, 32, fprint.convertNumToFourChaarPadString(deviceAddr))

    fastWriteByte1 = deviceAddr
    fprint.printTitleNumNoNewLine('fastWriteByte1', 5, 32, fprint.convertNumToFourChaarPadString(fastWriteByte1))    

    fastWriteByte2HighNibble =  0x00
    fastWriteByte2           = fastWriteByte2HighNibble | inputCodeHighByte
    fprint.printTitleNumNoNewLine('fastWriteByte2', 5, 32, fprint.convertNumToFourChaarPadString(fastWriteByte2))

    fastWriteByte3           = inputCodeLowByte
    fprint.printTitleNumNoNewLine('fastWriteByte3', 5, 32, fprint.convertNumToFourChaarPadString(fastWriteByte3))

    writeDeviceTwoBytes(i2cPortNum, deviceAddr, fastWriteByte2, fastWriteByte3)
    fprint.printEndExecuteFunction334()
    return

# *** Init Functions ***

def init():
    moduleName = initModuleName
    initModule(moduleName)
    return

def initModule(moduleName):
    fprint.printNewLine()
    fprint.printBeginExecuteFunction334()
    i2cPortNum       = initI2cPortNum
    i2cDemuxChNum    = initI2cDemuxChNum
    deviceNum        = initDeviceNum
    deviceBaseAddr   = initDeviceBaseAddr
    deviceSubAddr    = initDeviceSubAddr
    deviceAddr       = deviceBaseAddr | deviceSubAddr

    selectI2cDemuxCh(i2cDemuxChNum)

    fprint.printTitleStr('moduleName', 5, 32, moduleName)
    fprint.printTitleNumNoNewLine('i2cDeviceCh', 5, 32, i2cDemuxChNum)
    fprint.printTitleNumNoNewLine('deviceNum',   5, 32, deviceNum)
    fprint.printTitleNumNoNewLine('deviceBaseAddr', 5, 32, fprint.convertNumToFourChaarPadString(deviceBaseAddr))
    fprint.printTitleNumNoNewLine('deviceSubAddr', 5, 32, fprint.convertNumToFourChaarPadString(deviceSubAddr))
    fprint.printTitleNumNoNewLine('deviceAdr', 5, 32, fprint.convertNumToFourChaarPadString(deviceAddr))
    fprint.printEndExecuteFunction334()
    return

# *** Test Functions ***

def testModule(moduleName):
    resetDevice(i2cPortNum, deviceBaseAddr, deviceSubAddr)
    wakeupDevice(i2cPortNum, deviceBaseAddr, deviceSubAddr)
    setVolt(i2cPortNum, deviceBaseAddr, deviceSubAddr, testInputCode)
    return

    #setVolt(0, 0x62, 0x0, inputCodeOneThird)
    #setVolt(0, 0x62, 0x0, inputCodeOneQuarter)
    #setVolt(0, 0x62, 0x0, inputCodeHalf)
    #setVolt(0, 0x62, 0x0, inputCodeFull)
    #setVolt(0, 0x62, 0x0, inputCodeZero)

def test():
    moduleName = initModuleName
    initModule(moduleName)
    testModule(moduleName)
    return

# *** Main Function ***

def main():
    test()
    return

# *** Init Function Execution ***

#init()

# *** Main Function Execution ***

if __name__ == '__main__':
    main()

# *** End ***

/ ... to be continued, ...

3
  • Thanks for your suggestion and time. If you can give programming instruction it will help me to fix this issue.
    – uvan
    Commented Apr 30, 2018 at 9:50
  • I read that Jerwin Prabu has already solved your problem, so I am going slowly to learn how to program the device. If I can make it work, I will show you my code, in case you still need a python example.
    – tlfong01
    Commented May 1, 2018 at 6:51
  • Sorry, I didn't know you were waiting. I thought you already got the C++ version and so my python program is not necessary any more. Anyway I have uploaded my first working python for your reference. It is working, but needs more tidying up.
    – tlfong01
    Commented May 8, 2018 at 7:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.