Salve
voglio realizzare un braccio robotico per micromanipolazione di oggetti (da utilizzare assieme a un microscopio)
utilizzo 4 servi standard da modellismo 0-180° (HITEC HS311) movimenti avanti-indietro, up-down, destra-sinistra, get-release
Il primo prototipo utilizzava 8 pulsanti inseriti sulla breadboard per comandare di microstep i servi...funziona, ma...troppi cavi
Ora ho realizzato con processing una interfaccia grafica, ho caricato su arduino (UNO) la standard firmata
ma riesco a muovere i servi di microstep solo in senso orario con il comado arduino.analogWrite(servoPin3, 255);
non ruota in senso antiorario....qualcuno di voi ha fatto qualche progetto simile?
allego il codice di processing
//ROBOTIC MICROHANDLING
// Need G4P library download at
// http://www.processing.org/reference/libraries/
// Graphic Interface - G4P
// control servo on Arduino through GUI control
import processing.serial.*;
import cc.arduino.*;
import guicomponents.*;
PImage rear;
Arduino arduino; // Declare object (a variable of type arduino object)
//declare pin where servo are attached
int servoPin3 = 3;
int servoPin5 = 5;
int servoPin6 = 6;
int servoPin9 = 9;
// boolean variable coincident with the buttons
boolean up = true;
boolean down = true;
boolean fast = true;
boolean slow = true;
boolean left = true;
boolean right = true;
boolean back = true;
boolean forward = true;
boolean release = true;
boolean take = true;
void setup() {
size(410, 607);
rear = loadImage("realsteel.jpg");
println(Arduino.list());
//create a new arduino object and pass parameters( "this" refers to this sketch, name of serial port, speed)
arduino = new Arduino(this, Arduino.list()[0], 57600);
// attaches the servo on pin 3 to the servo object You need to set the mode of the pin that the servo is attached to, to SERVO
arduino.pinMode(servoPin3, Arduino.SERVO);
createGUI();
customGUI();
// Place your setup code here
}
void draw() {
background(rear);
if ( up ) {
}
else {
println (" up è cambiato " + up );
arduino.analogWrite(servoPin3, 255);
/*
arduino.digitalWrite(servoPin3, Arduino.HIGH); //write a servo angle 180 to an output pin
delay(1);
arduino.digitalWrite(servoPin3, Arduino.LOW);
delay(20);
*/
up = true;
}
if ( down ) {
}
else {
println (" down è cambiato " + down );
// arduino.digitalWrite(servoPin3, Arduino.HIGH); //write a servo angle 180 to an output pin
//delay(time90);
//arduino.digitalWrite(servoPin3, Arduino.LOW);
// delay(20);
down = true;
}
if ( fast ) {
}
else {
println (" fast è cambiato " + fast );
// arduino.digitalWrite(ledPin3, Arduino.HIGH);
delay(1000);
//arduino.digitalWrite(ledPin3, Arduino.LOW);
fast = true;
}
if ( slow ) {
}
else {
println (" slow è cambiato " + slow );
// arduino.digitalWrite(ledPin4, Arduino.HIGH);
delay(1000);
// arduino.digitalWrite(ledPin4, Arduino.LOW);
slow = true;
}
if ( left ) {
}
else {
println (" left è cambiato " + left );
// arduino.digitalWrite(ledPin5, Arduino.HIGH);
delay(1000);
// arduino.digitalWrite(ledPin5, Arduino.LOW);
left = true;
}
if ( right ) {
}
else {
println (" right è cambiato " + right );
// arduino.digitalWrite(ledPin6, Arduino.HIGH);
delay(1000);
// arduino.digitalWrite(ledPin6, Arduino.LOW);
right = true;
}
if ( back ) {
}
else {
println (" back è cambiato " + back );
// arduino.digitalWrite(ledPin7, Arduino.HIGH);
delay(1000);
// arduino.digitalWrite(ledPin7, Arduino.LOW);
back = true;
}
if ( forward ) {
}
else {
println (" forward è cambiato " + forward );
// arduino.digitalWrite(ledPin8, Arduino.HIGH);
delay(1000);
// arduino.digitalWrite(ledPin8, Arduino.LOW);
forward = true;
}
if ( release ) {
}
else {
println (" release è cambiato " + release );
// arduino.digitalWrite(ledPin9, Arduino.HIGH);
delay(1000);
// arduino.digitalWrite(ledPin9, Arduino.LOW);
release = true;
}
if ( take ) {
}
else {
println (" take è cambiato " + take );
// arduino.digitalWrite(ledPin10, Arduino.HIGH);
delay(1000);
// arduino.digitalWrite(ledPin10, Arduino.LOW);
take = true;
}
}
// Use this method to add additional statements
// to customise the GUI controls
void customGUI() {
}
Salve
si lato arduino carico lo StandardFirmata oppure StandardFirmata_2_2_forUNO
entrambi includono #include <Servo.h> la libreria servo per arduino e quindi i servi su arduino sono gestiti bene
Lato Processing esiste solo la libreria arduino che dichiaro con (vedere anche il mio codice processing sopra)
import processing.serial.; // aggiunta comunque per dire a processing di gestire la seriale
import cc.arduino.; // questa gestisce arduino
creo una variabile oggetto Arduino arduino;
e poi in setup() costruisco un nuovo oggetto Arduino
arduino = new Arduino(this, Arduino.list()[0], 57600);
successivamente i pin su cui sono collegati i servi vanno dichiarati con
arduino.pinMode(servoPin3, Arduino.SERVO); // al posto di OUTPUT va messo SERVO
La parte più difficile viene ora
in void draw() che in processing è l'analogo di void loop() per arduino
devo passare i comandi
Se utilizzo l'esempio di processing arduino_pwm
questo funziona...muove il servo a seconda di come muovo il mouse nella schermata size(512, 200); creata da processing
mouse a sinistra e il servo ruota a sinistra e analogamente a destra
Quindi per muovere il servo a destra ho scritto
arduino.analogWrite(servoPin3, 255);
e si muove di step a destra ogni volta che premo il pulsante sulla GUI
Ma per muoverlo a sinistra??
arduino.analogWrite(servoPin3, 0); rimane fermo
Qualche suggerimento?
se scrivi 0, il servo torna all'angolo 0° e ci rimane. se scrivi 255, dovrebbe andare all'angolo 180° e rimanerci.
quindi normalmente tu vorrai tenere il servo a 90°, ovvero 128, e poi in base a QUANTO vuoi muoverti a destra o a sinistra dai il numero.ù
Quindi quel valore è la POSIZIONE, non la velocità e direzione di rotazione.
magari ma temo non sia cosi...stò facendo delle prove ora
appena avvio l'applicazione di processing il servo va nella posizione centrale a 90°
se provo a forzarlo a mano per spostarlo non si muove da questa posizione centrale 90° quindi
ne presumo che la
arduino.pinMode(servoPin3, Arduino.SERVO);
invia correttamente alla StandardFirmata su arduino il comando di fermo
Ora... comando processing
arduino.analogWrite(servoPin3, 255);
alla prima volta che premo il pulsante sulla GUI non fa nulla al successivo che premo
muove di uno step a destra il servo ogni volta che premo il pulsante sulla GUI di processing
arduino.analogWrite(servoPin3, 0);
ruota a destra di un angolo circa 10°
arduino.analogWrite(servoPin3, 128);
ruota a sinistra a volte di pochi gradi a volte di circa 90° dopodichè si sente un ronzio come se fosse sempre alimentato
Il GND alimentazione servo (batteria 6V ) è comune al GND arduino
Come non detto.... hai ragione...ora ho provato la ServoFirmata (la mia ver. è 0022)
su processing
arduino.analogWrite(servoPin3, 180);
il servo ruota a destra 180° (rimane fermo ma emette un ronzio)
se scrivo
arduino.analogWrite(servoPin3, 178);
il servo ruota a destra 180°(fermo e nessun ronzio)
arduino.analogWrite(servoPin3, 0);
il servo ruota a sinistra 0° (fermo e nessun ronzio)
arduino.analogWrite(servoPin3, 90);
il servo si muove nella posizione centrale 90°(fermo e nessun ronzio)
continuo a far prove ora devo capire come fargli fare piccoli step
Consiglio per chi volesse usare processing, arduino e servo usate ServoFirmata
StandarFirmata include la #include <Servo.h>
ma non mi pare risponda bene come la ServoFirmata
Risolto!!
allego sotto il codice di processing per controllare il o i servi da processing usando la ServoFirmata su arduino spero possa tornare utile a qualcuno
(forse dovrei tradurlo in inglese perchè anche nel forum international mi pare brancolano nel buio)
come controprova o riprovato la StandardFirmata nulla per i servi non va bene
Ora domanda se nel ServoFirmata cambio "int value" con "float value" per passare al servo servos[PIN_TO_SERVO(pin)].write(value);
step più piccoli tipo 90.4 - 90.5 ecc. può funzionare o la libreria <Servo.h> di arduino ammette solo valori interi?
Grazie a tutti!!
allego il codice di processing
// goes from 0 degrees to 90 degrees and 90 to 180
// Need G4P library download at
// http://www.processing.org/reference/libraries/
// Graphic Interface - G4P
// control servo on Arduino through GUI control
import processing.serial.*;
import cc.arduino.*;
import guicomponents.*;
PImage rear;
Arduino arduino; // Declare object (a variable of type arduino object)
//declare pin where servo are attached
int pos = 90; // store position value
int servoPin3 = 3;
int servoPin5 = 5;
int servoPin6 = 6;
int servoPin9 = 9;
// boolean variable coincident with the buttons
boolean up = true;
boolean down = true;
boolean fast = true;
boolean slow = true;
boolean left = true;
boolean right = true;
boolean back = true;
boolean forward = true;
boolean release = true;
boolean take = true;
void setup() {
//size(410, 380);
size(410, 607);
rear = loadImage("realsteel.jpg");
println(Arduino.list());
//create a new arduino object and pass parameters( "this" refers to this sketch, name of serial port, speed)
arduino = new Arduino(this, Arduino.list()[0], 57600);
// attaches the servo on pin 3 to the servo object You need to set the mode of the pin that the servo is attached to, to SERVO
arduino.pinMode(servoPin3, Arduino.SERVO);
// attaches the servo on pin 5 to the servo object
//arduino.servoAttach(servoPin5);
createGUI();
customGUI();
// Place your setup code here
}
void draw() {
// background(200, 220, 200);
background(rear);
if ( up ) {
}
else {
println (" up è cambiato " + up );
for (pos = 90; pos >=1; pos-=1) { // goes from 90 degrees to 0 degrees
// in steps of 1 degree
arduino.analogWrite(servoPin3, pos);
delay(50);
}
up = true;
}
if ( down ) {
}
else {
println (" down è cambiato " + down );
for (pos = 0; pos < 90; pos += 1) { // goes from 0 degrees to 90 degrees
// in steps of 1 degree
arduino.analogWrite(servoPin3, pos);
delay(50);
}
down = true;
}
if ( fast ) {
}
else {
println (" fast è cambiato " + fast );
for (pos = 90; pos < 180; pos += 1) { // goes from 90 degrees to 180 degrees
// in steps of 1 degree
arduino.analogWrite(servoPin3, pos);
delay(50);
}
fast = true;
}
if ( slow ) {
}
else {
println (" slow è cambiato " + slow );
// arduino.digitalWrite(ledPin4, Arduino.HIGH);
delay(1000);
// arduino.digitalWrite(ledPin4, Arduino.LOW);
slow = true;
}
if ( left ) {
}
else {
println (" left è cambiato " + left );
// arduino.digitalWrite(ledPin5, Arduino.HIGH);
delay(1000);
// arduino.digitalWrite(ledPin5, Arduino.LOW);
left = true;
}
if ( right ) {
}
else {
println (" right è cambiato " + right );
// arduino.digitalWrite(ledPin6, Arduino.HIGH);
delay(1000);
// arduino.digitalWrite(ledPin6, Arduino.LOW);
right = true;
}
if ( back ) {
}
else {
println (" back è cambiato " + back );
// arduino.digitalWrite(ledPin7, Arduino.HIGH);
delay(1000);
// arduino.digitalWrite(ledPin7, Arduino.LOW);
back = true;
}
if ( forward ) {
}
else {
println (" forward è cambiato " + forward );
// arduino.digitalWrite(ledPin8, Arduino.HIGH);
delay(1000);
// arduino.digitalWrite(ledPin8, Arduino.LOW);
forward = true;
}
if ( release ) {
}
else {
println (" release è cambiato " + release );
// arduino.digitalWrite(ledPin9, Arduino.HIGH);
delay(1000);
// arduino.digitalWrite(ledPin9, Arduino.LOW);
release = true;
}
if ( take ) {
}
else {
println (" take è cambiato " + take );
// arduino.digitalWrite(ledPin10, Arduino.HIGH);
delay(1000);
// arduino.digitalWrite(ledPin10, Arduino.LOW);
take = true;
}
}
// Use this method to add additional statements
// to customise the GUI controls
void customGUI() {
}
se fa il ronzio vuol dire che sta sforzando e non va bene.. è normale che il servo non sia preciso al 100%.
non puoi usare i float, se vuoi maggiore precisione non devi dare gli angoli in °, ma usare direttamente i microsecondi del segnale. comunque non credere, i servi hanno un limite alla loro precisione in base alla loro qualità.
Perfetto !!
grazie writeMicroseconds è quello che ci vuole e ho modificato ServoFirmata cosi
/* This firmware supports as many servos as possible using the Servo library
* included in Arduino 0017
*
* TODO add message to configure minPulse/maxPulse/degrees
*
* This example code is in the public domain.
*/
#include <Servo.h>
#include <Firmata.h>
Servo servos[MAX_SERVOS];
void analogWriteCallback(byte pin, int value)
{
if (IS_PIN_SERVO(pin)) {
servos[PIN_TO_SERVO(pin)].writeMicroseconds(value);
}
}
void setup()
{
byte pin;
Firmata.setFirmwareVersion(0, 2);
Firmata.attach(ANALOG_MESSAGE, analogWriteCallback);
for (pin=0; pin < TOTAL_PINS; pin++) {
if (IS_PIN_SERVO(pin)) {
servos[PIN_TO_SERVO(pin)].attach(PIN_TO_DIGITAL(pin));
}
}
Firmata.begin(57600);
}
void loop()
{
while(Firmata.available())
Firmata.processInput();
}
Concordo i servi non sono precisi L'ideale sarebbe un piezo motor, ma costa troppo