Hi,
Operating System: Windows 7 professional service pack 1
Arduino Uno with arduino software version: 1.6.6
Processing Software version: 3.101 32 bit
Goal: create 55 ControlP5 knobs that correspond to 55 electric motors using the Arduino UNO. To be able to adjust all the knobs individually and then start/stop all the motors at once using one master button.
What I have so far: I have successfully controlled one motor with one knob, and I have already posted this on this forum here.
LINK- https://forum.processing.org/two/discussion/14006/example-code-controlling-electric-motors-with-a-controlp5-knob-and-adafruit-motor-shield-boards#latest
CODE-
Processing:
import processing.serial.*;
import controlP5.*; // import library for knob
Serial port; // Create serial port object
ControlP5 cp5; // defines the type "cp5" as a variable "type" defined in ControlP5 for knob
int myColorBackground = color(0,0,0);
int knobValue = 100;
Knob myKnobA;
Knob myKnobB;
void setup() {
port = new Serial(this, 9600);
size(700,400);
smooth();
noStroke();
cp5 = new ControlP5(this); //object created from library (what is this exactly?)
myKnobA = cp5.addKnob("knob") // "method" is add(ControllerInterface<?> theElement)
.setRange(0,255)
.setValue(50)
.setPosition(100,70)
.setRadius(50) // for knob
.setDragDirection(Knob.VERTICAL)
;
}
void draw() {
background(myColorBackground);
fill(knobValue);
rect(0,height/2,width,height/2);
fill(0,100);
rect(80,40,140,320);
}
void knob(int theValue) {
myColorBackground = color(theValue);
println("a knob event. setting background to "+theValue);
port.write(theValue);
}
Arduino:
#include <Wire.h>
#include <Adafruit_MotorShield.h>
#include "utility/Adafruit_PWMServoDriver.h"
// Create the motor shield object with the default I2C address
// Adafruit_MotorShield AFMS = Adafruit_MotorShield();
// DONT USE THIS ONE IF RUNNING MULIPLE MOTORS
// Or, create it with a different I2C address (say for stacking)
Adafruit_MotorShield AFMS = Adafruit_MotorShield(0X60); // 1st board if stacking
// Select which 'port' M1, M2, M3 or M4. In this case, M1
Adafruit_DCMotor *myMotor1 = AFMS.getMotor(1); // 1st board, M1
char val; // Data received from the serial port
void setup() {
Serial.begin(9600); // Start serial communication at 9600 bps
AFMS.begin(); // create with the default frequency 1.6KHz, this connects to the
// controller- need one for each motor? nope.
}
void loop() {
if (Serial.available()) { // If data is available,
val = Serial.read(); // read it and store it in val
}
myMotor1->setSpeed(val);
myMotor1->run(FORWARD);
delay(100); // Wait 100 milliseconds for next reading
}
I have made the following approaches and have tried the following things:
1) I attempted make a multiple knob GUI (2 knobs) that control 2 different motors, but have no way of assigning each knob to each motor because It I am unclear on how to differentiate serial data from one ControlP5 knob to another ControlP5 knob. The two knobs individually control the speed for the two motors simultaneously, as if they were the same motor. so in other words if you adjust the speed of one knob both motors will change speed and it doesn't matter which knob you change speed with. here is the code:
CODE-
Processing Side:
// Write data to the serial port according to the status of 2 ControlP5 Knob controlled
// by the mouse, and differenetiate the data between the two knobs when sending serially.
// Uses values from 0-255.
import processing.serial.*;
import controlP5.*; // import library for knob
Serial port; // Create serial port object
ControlP5 cp5; // defines the type "cp5" as a variable "type" defined in ControlP5 for knob
int myColorBackground = color(0,0,0);
int knobValue = 100;
int knobValue1 = 100; //for the second knob
Knob myKnobA;
Knob myKnobB;
void setup() {
port = new Serial(this, 9600);
size(1000,1000);
smooth();
noStroke();
cp5 = new ControlP5(this); //object created from library (what is this exactly?)
myKnobA = cp5.addKnob("knob") // "method" is add(ControllerInterface<?> theElement)
.setRange(0,255)
.setValue(50)
.setPosition(100,70)
.setRadius(50) // for knob
.setDragDirection(Knob.VERTICAL)
;
myKnobB = cp5.addKnob("knob1") // "method" is add(ControllerInterface<?> theElement)
.setRange(0,255) // for second knob
.setValue(50) // for second knob
.setPosition(300,1) // for second knob
.setRadius(50) // for knob
.setDragDirection(Knob.VERTICAL) // for second knob
; // for second knob
}
void draw() {
background(myColorBackground);
fill(knobValue);
rect(0,height/2,width,height/2);
fill(knobValue1); // was (0,100)
// rect(knobValue1); // was (80,40,140,320)
}
void knob(int theValue) {
myColorBackground = color(theValue);
println("a knob event. setting background to "+theValue);
port.write(theValue);
}
void knob1(int theValue1) { // for second knob
myColorBackground = color(theValue1); // for second knob
println("a knob event1. setting background to "+theValue1); // for second knob
port.write(theValue1); // for second knob
}
Arduino Side:
// Read data from the serial and turn a DC motor on or off according to the value. with adafruit motor driver
// board code included
#include <Wire.h> // ADAFruit
#include <Adafruit_MotorShield.h> // ADAFruit
#include "utility/Adafruit_PWMServoDriver.h" // ADAFruit
// Create the motor shield object with the default I2C address
// Adafruit_MotorShield AFMS = Adafruit_MotorShield(); // DONT USE THIS ONE IF RUNNING MULIPLE MOTORS //ADAFruit
// Or, create it with a different I2C address (say for stacking) // ADAFruit
Adafruit_MotorShield AFMS = Adafruit_MotorShield(0X60); // 1st board // ADAFruit
// Select which 'port' M1, M2, M3 or M4. In this case, M1 // ADAFruit
Adafruit_DCMotor *myMotor1 = AFMS.getMotor(1); // 1st board, M1 // ADAFruit
Adafruit_DCMotor *myMotor2 = AFMS.getMotor(2); // 2nd board, M2 // ADAFruit
char val1; // Data received from the serial port
char val2;
void setup() {
Serial.begin(9600); // Start serial communication at 9600 bps
AFMS.begin(); // create with the default frequency 1.6KHz, this connects to the // ADAFruit
// controller- need one for each motor? nope. // ADAFruit
}
void loop() {
if (Serial.available()) { // If data is available,
val1 = Serial.read(); // read it and store it in val
}
myMotor1->setSpeed(val1); // ADAFruit
myMotor1->run(FORWARD); // ADAFruit
delay(100); // Wait 100 milliseconds for next reading
if (Serial.available()) {
val2 = Serial.read();
}
myMotor2->setSpeed(val2);
myMotor2->run(FORWARD);
delay(100);
}
2) Searched and Studied passing strings through serial thinking that was a way to do it. I think I see how to pass a string serially but not how to differentiate data from one knob to one motor. does anyone know a good tutorial related to what I am doing?
3) Studying the applet page on the ControlP5 Page (http://www.sojamo.de/libraries/controlP5/). I think there is something I do not understand about reading the applet page of the conrolP5 website. I noticed they have the methods listed with no description.
Question1: How do you know how to use the code with all the methods listed?
Question2: How do you know what each Method does?
i was thinking getAddress, setAddress, & getValue would allow me to assign each knob to each motor. But I have not found how to implement them, an example, or able to decipher the Applet page for ControlP5.
LINK- http://www.sojamo.de/libraries/controlP5/
4) I studied the "SerialCalResponse" of the "Serial" examples built in to processing. It was not clear to me if:
Question1: Do I need 55 Serial Ports?
Question2: How do I differentiate the data coming from each object (ControlP5 knob) and then tell the arduino which motor corresponds to which knob. I will use a "case" function to differentiate but what am I differentiating?
Question3: Can I set up a monitoring command to tell the difference between the data coming from each knob or will it just display the value of the knob (0-255)?
5) I attempted to make an array of objects in order to generate the two knobs with one constructor but failed. it only generates one knob.
CODE-
// Create an array of 2 ControlP5 Knobs controlled
// by the mouse. uses values from 0-255.
import processing.serial.*; //import library for serial communication
import controlP5.*; // import library for knob
Serial port; // Create serial port object
ControlP5 cp5; // defines the type "cp5" as a variable "type" defined in ControlP5 for knob
int myColorBackground = color(0,0,0); // for GUI
int knobValue = 100; // for GUI
final int KNOB_NUMB = 2; // number of knobs for i for loop below
// Knob myKnobA;
// Knob myKnobB;
Knob[] myKnob = new Knob [KNOB_NUMB]; // attempting to use Knob as a data type
void setup() {
port = new Serial(this, 9600);
size(1000,1000);
smooth();
noStroke();
cp5 = new ControlP5(this); //object created from library (what is this exactly?)
// Initialize the balls' data
for (int i = 0; i < KNOB_NUMB; i++)
{
myKnob[i] = cp5.addKnob("knob") // "method" is add(ControllerInterface<?> theElement) the following indexes are per the object cp5
.setRange(0,255)
.setValue(50)
.setPosition(100+i*10,70)
.setRadius(50) // for knob
.setDragDirection(Knob.VERTICAL)
;
} // for
} // for setup()
void draw() {
background(myColorBackground);
fill(knobValue);
rect(0,height/2,width,height/2);
fill(0,100);
rect(80,40,140,320);
}
/*
void knob(int theValue) {
myColorBackground = color(theValue);
println("a knob event. setting background to "+theValue);
port.write(theValue);
}
*/
Question 1: Is only one knob showing up in the window because of how I am using the setPosition function above?
Please Post your answers here for the benefit of everyone