Unable to get MCP4725 DAC to work with simulated analog input.


This is my first post, first time working with Arduino so I hope I'm posting in the right section.

I'm working on inputting my air to fuel ratio from my wideband sensor controller (let's call it LM-2 for short) into my engine logger.

My engine logger (let's call it MPVI for short) plugs into the OBD2 diagnostics port of my car and with some software can log several engine parameters such as engine RPM, Load, Mass Air Flow Frequency, Oil pressure, etc. It can also log four 0-5V DC analog inputs. The LM-2 has what they call an analog output that is supposed to send out 0-5V DC proportional to what the air to fuel ratio is.

I log the air to fuel ratio in Lambda. A value of Lambda = 1 means that the engine is running at a stochiometric level, regardless of fuel used. Values of less than 1 are considered a rich mixture and values above 1 are considered a lean mixture.

The problem is that the LM-2 puts out a simulated 0-5V analog value, people have found it to the be a square wave, not the sine wave that the MPVI is expecting. The result of this is that the data that is logged turns out to be useless.

Someone had already solved this issue by using an Arduino Uno and a MCP4725 DAC to take the square waves from the LM-2 and changing them into true analog 0-5V sine waves. Unfortunately all that person left as information was the components he used and some code. I tried my best to emulate what he had done, but I did not get any output voltage from the DAC. A friend of mine has helped me make some changes but now it only outputs a constant voltage as the Lambda reading in the logger is always around 0.80 Lambda, regardless of the actual measured value.

Attached is the diagram of how I have it wired up and below are what the components are:

  • The box on the top with 2 pins are the Innovate LM-2 wideband controller outputs.
  • The middle box with 6 pins is the Sparkfun MCP4725 DAC
  • The bottom box with 8 pins is the MPVI logger.

I'm using an Arduino Uno and a HiLetgo MCP4725 DAC.

Below is the code I'm using:

#include <Wire.h>
#include <Adafruit_MCP4725.h>
Adafruit_MCP4725 dac;
int ledState = LOW; // ledState used to set the LED
unsigned long ledStateMillis = 0; // will store last time LED was updated
int inputLM2 = 0;
uint16_t outputDAC = 0;

void setup()
  // initialize digital pin LED_BUILTIN as an output.

  // Indicate start of setup

  // Sensor input
  pinMode(A1, INPUT);

  // Set A2 and A3 as Outputs to make them our GND and Vcc,
  // which will power the MCP4725
  pinMode(A2, OUTPUT);
  pinMode(A3, OUTPUT);
  digitalWrite(A2, LOW);  // Set A2 as GND
  digitalWrite(A3, HIGH); // Set A3 as Vcc

  // wait 500 millisecs to allow MCP4725 breakout board to power up

  // This is the I2C Address of the sparkfun's MCP4725 breakout board (adafruits's board might be different)
  // For devices with A0 pulled LOW, use 0x60 (A0 pulled to GND).
  // For devices with A0 pulled HIGH, use 0x61

  // Indicate end of setup

void loop()

  // Read LM-2 value
  inputLM2 = analogRead(A1);

  // Re-map sensor range
  outputDAC = map(inputLM2, 0, 1023, 0, 4095);

  // Write to dac
  dac.setVoltage(outputDAC, false);

  // wait 10 milliseconds

// setupBlink will quickly flash the built in LED and pause for a second
void setupBlink(int flashCount)
  for (int i = 0; i < flashCount; i++)
    digitalWrite(LED_BUILTIN, HIGH);  // turn the LED on
    delay(50);                       // wait
    digitalWrite(LED_BUILTIN, LOW);   // turn the LED off
    delay(100);                       // wait

// loopBlink will toggle the built in LED for 1 second
void loopBlink()
  unsigned long currentMillis = millis();

  if (currentMillis - ledStateMillis >= 1000) {
    // save the last time LED blinked
    ledStateMillis = currentMillis;

    // if the LED is off turn it on and vice-versa:
    ledState = (ledState == LOW) ? HIGH : LOW;

    // set the LED with the ledState of the variable:
    digitalWrite(LED_BUILTIN, ledState);

And here is the code that I used as a basis that did not output any voltage, but the other person had used:

// Input 0-5v PWM or Analog on (A1) output DAC out 0-5v linear.
#include <Wire.h>
#include "i2c.h"
#include <Adafruit_MCP4725.h>
Adafruit_MCP4725 dac;
#define DAC_RESOLUTION (8)
int AFRSignal;
void setup()
void loop()
  int AFRSignal = analogRead(A1);
  float DAC = map(AFRSignal, 0, 1023, 0, 4095);
  dac.setVoltage(DAC, false);
  delay (10);

Please let me know what I have missed or wired incorrectly.

You might want to check your drawing. You have ground connected to A2, VCC to A3, as shown it will never work. Why not draw a schematic, not a frizzy thing, and post that, it would help a lot. Be sure to show all power and ground connections and note the vehicle connections.

The problem is that the LM-2 puts out a simulated 0-5V analog value, people have found it to the be a square wave, not the sine wave that the MPVI is expecting.

It sounds to me like the LM2 has some sort of pulsed 0-5v digital output, where the duty cycle contains the information. You can not read that with analogRead().

You will need to use an RC filter to convert the pulsed signal into a smoothed analog value which you can read with the Arduino.

In the tutorial/code from the person which worked where did the input to A0 come from and was it conditioned?

It's not clear to me why the analog output from the RC filter can not be a direct input to the MPVI and why you need to go through the Arduino and DAC.

Not so long ago I posted code to produce a sine wave out of an Arduino without the use of an external DAC. May work for you with some adaptations. Does the logger expect variable frequency or variable amplitude?

The new 0 and 1 series AVR processors can read the duty cycle of a PWM signal directly using a B type timer. One of the newer Arduinos uses an ATmega of that series, I forgot which one, so far I only used the ATtiny412... good stuff. Really good.

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