Control MCP4728 with Bela Trill

Hello everyone. I'm working on a project where I have to control voltage output value from MCP4728 using data value read from Trill bar sensor. Is it possible to achieve this in Arduino?

#include <Adafruit_MCP4728.h>
#include <Wire.h>
#include <Trill.h>

Adafruit_MCP4728 mcp;

Trill trillSensor1;

boolean touchActive = false;

void setup() {
  Serial.begin(115200);
   int ret1 = trillSensor1.setup(Trill::TRILL_BAR);
  if(ret1 != 0) {
  
     pinMode(9, OUTPUT);
  } 
  while (!Serial)
    delay(10);

  Serial.println("Adafruit MCP4728 test!");

    if (!mcp.begin()) {
      Serial.println("Failed to find MCP4728 chip");
      while (1) {
        delay(10);
      }
    }

}

void loop() {
  // put your main code here, to run repeatedly:
   if(trillSensor1.getNumTouches() > 0) 
    for(int i = 0; i < trillSensor1.getNumTouches(); i++) {
    mcp.setChannelValue(MCP4728_CHANNEL_A, i);
    mcp.setChannelValue(MCP4728_CHANNEL_B, i);
    mcp.setChannelValue(MCP4728_CHANNEL_C, i);
    mcp.setChannelValue(MCP4728_CHANNEL_D, i); 
    delay(5);   
  }

  {
  // Read 20 times per second
  delay(50);
  trillSensor1.read();
int touchValue = trillSensor1.touchLocation(0)/255;
int brightness = map(touchValue, 0, 255, 0, 255);
analogWrite(9, brightness);
  }
   if(trillSensor1.getNumTouches() > 0) 
    for(int i = 0; i < trillSensor1.getNumTouches(); i++) {
    
    }
  {
    Serial.println("");
    touchActive = true;
 }
}

This is what I got so far but I couldn't get it to work. I'm still pretty new to programming so I would really appreciate some help from you guys. Thank you in advance.

I can't see any reason why not.

Not really good enough, it what way does it "not work"? Where is the code getting to?

With embedded computing the software is only half the story, the other half is the hardware, so please post a schematic of your wiring, along with a photograph of your setup. Note we need to see both.

Is the MCP4728 you have a chip or is it mounted on a breakout board? If the latter can you link to the board you have used.

i recently breadboarded a circuit using the mcp23017 i/o expander, which i've used before and actually designed/built a PCB using it

of course it didn't work. i first found code for an 12c bus scanner to make sure i wired it correctly for the address i expected

then i wrote code to display the i2c registers to make sure they were programmed as expected. finally i wrote routines i could exercise with commands thru the serial monitor to read/write register to read/change pin states

since you're using a library, you may not need those commands but do need to insure it's wired correctly. don't forget the pull-up resistors on SCL/SDA and Nreset

The datasheet says
The user can program the DAC input codes, device configuration bits, and I2C address bits to the non-volatile memory (EEPROM) by using I2C™Compatible interface commands.

So first thing to do is using an I2C-scanner to find the momentary used default I2C-adress

best regards Stefan


Thank you for looking into it. Sorry for the late reply

Meanwhile, I've made a schematic and some changes to the code. The MCP4728 is mounted on a breadboard and it's Adafruit MCP4728

#include <Trill.h>
#include <Adafruit_MCP4728.h>
#include <Wire.h>

Adafruit_MCP4728 mcp;

int A_Volt = 0;

Trill trillSensor1;

boolean touchActive = false;

void setup() {
  // Initialise serial and touch sensor
  Serial.begin(115200);
  int ret = trillSensor1.setup(Trill::TRILL_BAR);
  if(ret != 0) {
    Serial.println("failed to initialise trillSensor");
    Serial.print("Error code: ");
    Serial.println(ret);
   
  }

}


void loop() {

  
  // Read 20 times per second
  delay(50);
  trillSensor1.read();
  
int touchValue = trillSensor1.touchLocation(0);
int A_Volt = map(touchValue, 0, 3200, 0, 4095);
  

  mcp.setChannelValue(MCP4728_CHANNEL_A, A_Volt);



  if(trillSensor1.getNumTouches() > 0) {
    for(int i = 0; i < trillSensor1.getNumTouches(); i++) {
        Serial.print(trillSensor1.touchLocation(i));
        Serial.print(" ");
        Serial.print(trillSensor1.touchSize(i));
        Serial.print(" ");
    }

    
{
    Serial.println("");
    touchActive = true;
  }
  
// else if(touchActive) {
    // Print a single line when touch goes off
    Serial.println("0 0");
    touchActive = false;
  }

}

So I'm trying to control the value of A_Volt in

 mcp.setChannelValue(MCP4728_CHANNEL_A, A_Volt);

using a Trill Bar sensor

Do you know that on a UNO that A4 is the exact same processor output as the SDA connection on the other side of the board? Also A5 is the exact same processor output as the SCL connection on the other side of the board.

This means the Trill bar and the MCP4728 must present the I2C interface with different addresses. Have you tried running an I2C scanner code to see if the two addresses you expect to see are seen. The Trill Bar has address links on the board where you can change the I2C address.

You are still not saying what it is exactly the code does and what you want them to do.

What printed output do you see on the serial monitor?

You are trying to do too much at once in this sketch. Just get the Trill bar working and simply printing out values before you even think of doing anything with these numbers.

The I2C lines will normally need a 4K7 pull up resistor on them somewhere, you don't show any.

Add a delay(400); statement after the serial begin if you don't see anything printed.

Yes, would it be better to bus both Trill Bar and MCP4728 into one SDA and SCL? I never tried to use multiple devices on Arduino.

This is what I got when I ran I2C scanner code. Should both devices have the same address?

So I only got the Trill Bar to work in the code at the moment. I can go from 0 to 3200 and it stops generating number when I disconnect from the sensor.

Wasn't aware of this. I'll try it.

Thank you for helping again.

No, it is fine the way you have them but I wanted to know if you knew about it.

No both devices must have different addresses. It looks like the scanner is picking up the addresses correctly. The device at 0x20 is the Trill bar. So the one at 0x28 must be the MCP4728, although by coincidence is also the default address of the Trill Square.

Have you tried the code in the link you posted to the AdaFruit page, the one that just sends out the voltages to the MCP4728? Does that give you anything on that chip you can measure?

It's weird. It looks like MCP4728 is being recognized but not sending out any voltage output. Would it be because of the 4k7 pull up resistor you mentioned? I tried this code on Adafruit page

// Basic demo for configuring the MCP4728 4-Channel 12-bit I2C DAC
#include <Adafruit_MCP4728.h>
#include <Wire.h>

Adafruit_MCP4728 mcp;

void setup(void) {
  Serial.begin(115200);
  while (!Serial)
    delay(10); // will pause Zero, Leonardo, etc until serial console opens

  Serial.println("Adafruit MCP4728 test!");

  // Try to initialize!
  if (!mcp.begin()) {
    Serial.println("Failed to find MCP4728 chip");
    while (1) {
      delay(10);
    }
  }

  mcp.setChannelValue(MCP4728_CHANNEL_A, 4095);
  mcp.setChannelValue(MCP4728_CHANNEL_B, 2048);
  mcp.setChannelValue(MCP4728_CHANNEL_C, 1024);
  mcp.setChannelValue(MCP4728_CHANNEL_D, 0);
}

void loop() { delay(1000); }

Thank you

Are you using the MCP4728 or the MCP4728A?
They have different I2C addresses.

This page of the Adafruit site

Tells you about this.

It also says that this chip has a 10K I2C pull-up resistor fitted so you will not need the external ones I said about.

Have you read all the pages about this board?
That first example just sets the D/A just once, try setting it in the loop function.

Also check the physical wiring of your part.

I've tried all the I2C addresses shown in the page but I had no luck. I also tried to set the D/A in the loop like this

// Basic demo for configuring the MCP4728 4-Channel 12-bit I2C DAC
#include <Adafruit_MCP4728.h>
#include <Wire.h>

Adafruit_MCP4728 mcp;

void setup(void) {
  Serial.begin(115200);
  while (!Serial)
    delay(10); // will pause Zero, Leonardo, etc until serial console opens

  Serial.println("Adafruit MCP4728 test!");

  // Try to initialize!
  if (!mcp.begin(0x28)) {
    Serial.println("Failed to find MCP4728 chip");
    while (1) {
      delay(10);
    }
  }

  mcp.setChannelValue(MCP4728_CHANNEL_A, 2048);
  mcp.setChannelValue(MCP4728_CHANNEL_B, 2048);
  mcp.setChannelValue(MCP4728_CHANNEL_C, 1024);
  mcp.setChannelValue(MCP4728_CHANNEL_D, 0);
}

void loop() {

  mcp.setChannelValue(MCP4728_CHANNEL_A, 2048);
  mcp.setChannelValue(MCP4728_CHANNEL_B, 2048);
  mcp.setChannelValue(MCP4728_CHANNEL_C, 1024);
  mcp.setChannelValue(MCP4728_CHANNEL_D, 0);
}


I tried it with one of my oscillators and it does look like it's sending out voltage. However, I cannot seem to control the value with changing numbers on this line.

mcp.setChannelValue(MCP4728_CHANNEL_A, 4095);

Seems like it's stuck on 4095 by the range of pitch jump I'm hearing whenever I plug it in the oscillator. Also when I switch power to 3.3v I get half the range.

That is not a surprise because the resolution of the D/A is 12 bits and 4095 is the biggest number you can get from 12 bits.

What voltage do you measure for the four channels when you use these numbers?

void loop() {

  mcp.setChannelValue(MCP4728_CHANNEL_A, 4095);
  mcp.setChannelValue(MCP4728_CHANNEL_B, 2048);
  mcp.setChannelValue(MCP4728_CHANNEL_C, 1024);
  mcp.setChannelValue(MCP4728_CHANNEL_D, 512);
  delay(500);
}

The voltage should half for every channel.

Unfortunately I don't have a voltmeter with me so the only way to measure the voltage difference is to hear it with the oscillator. But I did try changing numbers in the code but there was no change and it seemed like I was getting max voltage output throughout all channels

Thank you

Not sure I understand what you mean by oscillators.

Anyway when you get your meter back, if all outputs are the same, I think it might be time to ask in the AdaFruit forum they are more product support than here.

My suspicion is still that you have the wiring wrong, or not making proper connection. Show them a better photo than you posted here. One that shows where all the wires go and without the Trill Bar, just to keep things simple.

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