Go Down

Topic: Virtual, variable resistors, with saved presets recallable by MIDI (Read 4448 times) previous topic - next topic

Stoopalini

I've been reading a bit more, and have a question related to controlling a digital POT with an analog POT through the Arduino Nano.

The existing analog POTs are 100k, and I was planning to connect then to the Arduino.  H as 5v, L as ground, and W as the analog input.  Then read the signal and map it over to the digital POT (I've ordered a couple MCP41100 chips). 

I think from a spec POV, I'm 90% ok here.  The 41100 spec sheet states the max voltage on the A, B, and W pins are Vcc +1v.  I measured 5.5v on the existing POT, and I'll be feeding the digi-pot 5v, so I should be good there. 

The 41100 is a 100k sweep, same as the analog ones; so I'm good there. 

What I'm concerned about is the 100k analog pot hooked up to the 5v, ground, and ADC input of the Arduino.  1st concern is if the 100k load will generate too much current for the Nano to handle.  2nd concern is if the reading will be accurate since the ADC input seems to be optimized for a 10k impedance input. 

I think this is leading me to the conclusion I need to replace the analog POTs with 10k ones, if I am to go the digi-pot route. 

And, it would also mean I cannot use the servo solution at all, since the dual POTs have both sweeps the same at 100k.  Unless there are dual rotary POTs out there with one sweep at 100k and the other at 10k. 

allanhurst

The analog input of an atduinos is of very high impedance, so 100k pots are perfectly usable. Lower values are often recommended for very slighly better accuracy and better noise immunity.

Either 100k or 10k would be fine.

You can buy special pots with different tracks - I think bourns do them - but adding a servomotor would not be very easy.

Allan.

Stoopalini

Great, thanks.  I ordered the parts today so I can begin experimenting. 

On another note:  is there a particular online circuit design tool which works well for Arduino layout?  I want to get things "on paper" from a design POV so I can begin experimenting when the parts arrive. 

allanhurst

There are loads of schematic capture/PCB layout packages - if you search this site you'll find lots of recommendations.

Allan

Stoopalini

I decided to try DigiKey's online tool, and here's my 1st stab at the diagram. 

I'm not sure if both DigiPOTs can share the same CS, SCK, and SI pins though.  The Arduino communicates through SPI, correct?  And I see in my reading that in the code, you have to define an address, or device number, for the DigiPOT, in order to send a command to it.  So does this mean they can share the same communication buss/pins, and the code is written to differentiate between the two?

Or do they each need their own pins for communicating the value to be written each one?

Thanks again for the assistance.



allanhurst

You need a seperate cs to each controlled SPI device to select it

Allan

Stoopalini

    Ok, thanks.  Are there limitations to which D pins I can use for CS, or is this configurable in the code and I can use any available D pin?

    Just to confirm my understanding:

    • CS = "Chip Select".  A digital signal pin, connected to a device, which is pulled high to signify to the device that the message being transmitted by the Ardunio at that time is intended for it to receive and process
    • SCK = "Signal Clock".  A digital signal pin which transmits a square wave clock cycle, used to synchronize communication among the components, for signal and message timing.
    • MOSI = "Master Out Slave In".  Term used for the Ardunio (as the Master) sending commands out to Slave devices.
    • MISO = "Master In, Slave Out".  Term used for the Ardunio (again, the Master) receiving data from a slave device.


    Am I understanding this properly?  And if so, I assume I don't need MISO for this, considering the DigiPOT won't need to send any data back to the Ardunio, since the values from the analog POTs will be used to store presets. 

    This is how I modified the graphic, assuming what I typed above is accurate:


[/list]

allanhurst

The protocal requires acknowledges from the slave, so you need the MOSI

Allan

Stoopalini

Do you mean MISO?  Or am I confused on the two terms (MISO and MOSI)?

allanhurst

Yes - sorry. But you need them both

Allan.

No big deal - just another wire.....

Allan

Stoopalini

No big deal - just another wire.....
Right, but the MCP41100 (single POT version) doesn't have an SO pin.  I read through the datasheet a few times, and the MCP42xxx version (dual POTs) has an SO pin, but the datasheet only mentions it for daisy chaining devices together.  My MCP41100's will be here this week.

Maybe the Ack comes back through the SI pin?

MCP41100 Datasheet

I think I'll use the parts I ordered to do my learning and testing, but have been looking into getting some 10 bit resolution POTs for the final implementation.  I understand this makes it challenging due to the difference in message lengths, and the Mega328's 8bit message length (so there's a need to send three messages instead of two, meaning one command message and two data messages), but the analog POT will be read with values of 0-1023, so for optimal control over the parameters in the pedal, I think I'll want to utilize that level of resolution forn the values being sent back to the DigiPOTs. 

Still learning and planning ... Hope to be testing soon

allanhurst

No - it's serial out for the next device in the daisy chain

Allan

Stoopalini


allanhurst

for this device you don't need it. I hadn't looked up it's spec before my previous reply.....

Allan

Stoopalini

No problem at all, I really appreciate your help.  I feel like I accomplished something today!

For a test of my understanding, I setup a flashing LED, with speed of the flash controlled by a Potentiometer (POT1).  Simple enough.

Then I added a second potentiometer (POT2) to act as a memory location selection device (0 - 99), and added 2 buttons.  Button1 for storing the value, and button 2 for recalling.

So, when turning POT1, the speed of the flashing changes accordingly.  Then turning POT2 allows selection of a number from 0 -99 (using a divider and the (round) command).  Pressing Button 1 stores the value into an array using POT2's value (after normalizing it into the 0 - 99 scale) as the location.  Button 1 recalls the stored value from the array, and sets the LED flashing at whatever value it retrieved.

Then the LED stays flashing at the recalled rate until POT1 is moved (then it goes to real time) or until another preset is recalled.

Again, I truly appreciate all the help and input you've given me.  If you see anything I did wrong, or just inefficient, I'm open to learning more!

I'm still awaiting the DigiPOTs to be delivered so I can get to experimenting with SPI.

Here is the board and connections:





And here is the code:

Code: [Select]


    // Pin Selects
int potvalPin = 3;    // select the input pin for value potentiometer
int potpresetPin = 1;   // select input pin for preset control potentiometer
int ledPin = 2;   // select output pin for the LED
int setPin = 7;  // Select input pin for button to set a preset
int recallPin = 5;   // select input pin for button to recall a preset

    // Variable Definition
int setbutton = 0;  // variable to store state of the preset set button
int recallbutton = 0;  // variable to store the state of the preset recall button
int potstoredval = 0; // variable to store the "value potentiometer" previous value for comparison
int potreadval = 0;       // variable to store the real time value from value potentiometer
int actualvalue = 0;  //  variable to store the current value
int preset = 0;     // variable to store preset number from preset potentiometer

    //Array Definition
int myPresets[100];   // create array to store presets

    // Initialize
void setup() {
  pinMode(ledPin, OUTPUT);  // declare the ledPin as an OUTPUT
  pinMode(setPin, INPUT);  // declare the presetsetPin as an INPUT
  pinMode(recallPin, INPUT);  // declare the presetrecallPin as an INPUT
  potreadval = 1023 - analogRead(potvalPin);  // read current value from the value pot
  actualvalue = potreadval;  // set current value to pot read value
  Serial.begin(9600);  // establish serial communication for monitoring
}

    //Main Code
void loop() {
  potreadval = 1023 - analogRead(potvalPin);  // read the value POT's real time position and store it
  setbutton = digitalRead(setPin);  // Read the set button's state
  recallbutton = digitalRead(recallPin);  //  read the recall button's state
  if(potreadval != potstoredval) RealTime();  // if the value POT has been turned, go into real time mode
  if (setbutton == HIGH) SetPreset();  //  if the SET button is pressed, go to subroutine to store the preset
  if (recallbutton == HIGH) RecallPreset();  //  if the RECALL button is pressed, go to subroutine to recall the value

  digitalWrite(ledPin, HIGH);  // turn the ledPin on
  delay(actualvalue);                  // stop the program for some time
  digitalWrite(ledPin, LOW);   // turn the ledPin off
  delay(actualvalue);                  // stop the program for some time
  
  Serial.print ("Actual Value (flashing) = ");
  Serial.println (actualvalue);
  Serial.print ("Pot Read Value = ");
  Serial.println (potreadval);
  Serial.print ("Pot Stored Value = ");
  Serial.println (potstoredval);
}

    // Realtime Mode
void RealTime() {
  Serial.println ("Start RealTime Subroutine");
  potreadval = 1023 - analogRead(potvalPin);    // read the value from the sensor
  actualvalue = potreadval;  // set flashing speed
  potstoredval = actualvalue;  // set previous value
}

    // Store Preset Mode
void SetPreset() {
  Serial.println ("Start SetPreset Subroutine");
  preset = round(analogRead(potpresetPin)/10.32);  // read preset POT position, and determine which preset between 0 - 99 it cooresponds to
  potreadval = 1023 - analogRead(potvalPin);  // read the value POT
  myPresets[preset] = potreadval;  // write the value of the value POT to the array, in the position of the value of the preset POT  
}

    // Recall Preset Mode
void RecallPreset() {
  Serial.println ("Start RecallPreset Subroutine");
  preset = round(analogRead(potpresetPin)/10.32);  // read preset POT position, and determine which preset between 0 - 99 it cooresponds to
  actualvalue = myPresets[preset];  //  set flashing value to the recalled value
}

Go Up