For the Smoothie project, a MCP4351 SPI digital potentiometer will be used to control the current setting of the 4 A4983.
That will allow direct control of the current settings from the firmware / via serial commands, and automatic benchmarking of the current settings.
Todays mission was to get it to work on a breadboard.
Here, a MCP4331 was used instead of the MCP4351, but it's basically the same thing, with less resolution.
It was soldered on a breakout board … it did not work at the first try, but finally hot air + solder paste did the job.
Now, the datasheet is one of the bad kind : no clear indication on how to get started quickly … it took about 4 hours to figure that the reset pin must be kept HIGH.
Once that was ok, it was quick to get it to work with the BusPirate.
Quick story : Mode 5 ( SPI ), any speed, default options ( except Normal (H=3.3V, L=GND) output ), Power On ( W command ), Pullup resistors On ( P command ), and it starts responding.
Pin positions :
BusPirate pin | Cable color | MCP43XX Pin number | MCP43XX Pin function | |
---|---|---|---|---|
GND | Brown | 5 | VSS | |
+3.3V | Red | 15 | VDD | Also connect to pin 13 : Reset |
MISO | Black | 14 | SDO | |
CS | White | 2 | CS | |
MOSI | Grey | 4 | SDI | |
CLK | Purple | 3 | SCK |
Now in the Bus Pirate console, we can do things like this :
SPI>M5 1. HiZ 2. 1-WIRE 3. UART 4. I2C 5. SPI 6. JTAG 7. RAW2WIRE 8. RAW3WIRE 9. PC KEYBOARD 10. MIDI 11. LCD (1) >5 Mode selected Set speed: 1. 30KHz 2. 125KHz 3. 250KHz 4. 1MHz (1) > Clock polarity: 1. Idle low *default 2. Idle high (1) > Output clock edge: 1. Idle to active 2. Active to idle *default (2) > Input sample phase: 1. Middle *default 2. End (1) > Select output type: 1. Open drain (H=Hi-Z, L=GND) 2. Normal (H=3.3V, L=GND) (1) >2 READY SPI>P WARNING: pins not open drain (HiZ) 1. Pull-ups off 2. Pull-ups on (1) >2 Pull-up resistors ON SPI>W POWER SUPPLIES ON SPI>{0b00001100 0} // Read first potentiometer value CS ENABLED WRITE: 0x0C READ: 0xFE WRITE: 0x00 READ: 0x40 // Returns 0x40 CS DISABLED SPI>{0b00000000 5} // Write 0x05 there CS ENABLED WRITE: 0x00 READ: 0xFF WRITE: 0x05 READ: 0xFF CS DISABLED SPI>{0b00001100 0} // Read first potentiometer value again CS ENABLED WRITE: 0x0C READ: 0xFE WRITE: 0x00 READ: 0x05 // Returns 5 as set CS DISABLED SPI>
Checking with a multimeter shows the resistance at the corresponding pins changing : hurrah !
A word on the commands : First 4 bits are the memory address, first potentiometer ( 0000 ) in our case. The next two are the command ( 00 = write, 11 = read, why not the other way ??? ). The next 10 bits are data, but for writing to potentiometers, you really only use 7 or 8 bits depending on your chip. The datasheet is pretty understandable on this.
Now all we need to do is have the same thing from an arduino.
The pin connections from an arduino are similar, really nothing to say on this side.
Here is the code on the arduino side :
- define SCK_PIN 13
- define MISO_PIN 12
- define MOSI_PIN 11
- define SS_PIN 10
class SPI{
public: SPI(){ // initialize the SPI pins pinMode(SCK_PIN, OUTPUT); pinMode(MOSI_PIN, OUTPUT); pinMode(MISO_PIN, INPUT); pinMode(SS_PIN, OUTPUT);
// enable SPI Master, MSB, SPI mode 0, FOSC/4 this->mode(0);
}
void mode(byte config){ byte tmp; // enable SPI master with configuration byte specified SPCR = 0; //SPCR = (config & 0x7F) | (1<<SPE) | (1<<MSTR); SPCR |= (1<<SPE)|(1<<MSTR)|(1<<SPR0); SPDR = 0x01; tmp = SPSR; tmp = SPDR; }
byte transfer(byte value){
SPDR = value; while (!(SPSR & (1<<SPIF))) ; return SPDR;
}
byte transfer(byte value, byte period){
SPDR = value; if (period > 0) delayMicroseconds(period); while (!(SPSR & (1<<SPIF))) ; return SPDR; }
};
SPI Spi = SPI();
void setup(){
Serial.begin(9600);
}
void loop(){
for( byte i = 0; i < 129; i++ ){ digitalWrite(10,LOW); Spi.transfer(0b00000000); Spi.transfer(i); digitalWrite(10,HIGH);
digitalWrite(10,LOW); Spi.transfer(0b00001100); byte returned = Spi.transfer(0b11000011); digitalWrite(10,HIGH); //Serial.print(i,DEC); //Serial.print(' '); //Serial.println(returned,BIN); //Serial.println();
delay(1); }
}
</code>
What this code does, it just loops thru all the values the first potentiometer can have … if you connect a LED there, you even can see it lighting up slowly in a loop.
It took a bit of time to get this too working, but now it does.
That's all for today, next : the A4983 on a breadboard !