Macroschlitten: Unterschied zwischen den Versionen
Zeile 15: | Zeile 15: | ||
Stepper läuft mit 12V | Stepper läuft mit 12V | ||
− | + | === Ardunio-Code === | |
<div class="mw-collapsible mw-collapsed"> | <div class="mw-collapsible mw-collapsed"> | ||
<syntaxhighlight lang="c" line enclose="div"> | <syntaxhighlight lang="c" line enclose="div"> | ||
Zeile 166: | Zeile 166: | ||
</div> | </div> | ||
− | + | === Processing-Code === | |
+ | <div class="mw-collapsible mw-collapsed"> | ||
<syntaxhighlight lang="c" line enclose="div"> | <syntaxhighlight lang="c" line enclose="div"> | ||
import processing.serial.*; | import processing.serial.*; | ||
Zeile 279: | Zeile 280: | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
+ | </div> | ||
− | + | === Knitty: passap Firmware === | |
− | Knitty: passap Firmware | + | <div class="mw-collapsible mw-collapsed"> |
− | |||
<syntaxhighlight> | <syntaxhighlight> | ||
////////////////////////////////////////////////////////////////////////////// | ////////////////////////////////////////////////////////////////////////////// | ||
Zeile 684: | Zeile 685: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
+ | </div> |
Version vom 16. Juni 2014, 14:47 Uhr
Macroschlitten Status: stable | |
---|---|
Beschreibung | |
Autor: | ptflea |
Version | 0.5 |
PayPal |
Stepper läuft mit 12V
Ardunio-Code
1#include <AFMotor.h>
2#include <AccelStepper.h>
3
4// Connect a stepper motor with 48 steps per revolution (7.5 degree)
5// to motor port #2 (M3 and M4)
6int incomingByte;
7char Data[8];
8int i;
9unsigned long Zeit;
10int bewegung;
11int schritte;
12
13int motorStepsPerRev = 200;
14float currentMaxSpeed = 1200.0;
15float currentAcceleration = 300.0;
16const int stepType = INTERLEAVE;
17
18AF_Stepper motor1(motorStepsPerRev, 2);
19AF_Stepper motor2(motorStepsPerRev, 1);
20
21
22void forwarda() {
23 motor1.onestep(FORWARD, stepType);
24}
25void backwarda() {
26 motor1.onestep(BACKWARD, stepType);
27}
28
29AccelStepper accelA(forwarda, backwarda);
30
31
32void forwardb() {
33 motor2.onestep(FORWARD, stepType);
34}
35void backwardb() {
36 motor2.onestep(BACKWARD, stepType);
37}
38
39AccelStepper accelB(forwardb, backwardb);
40
41int range_in;
42int byte_in[2]; // variable to store the VALID data from the port
43char nextMsg;
44
45
46void setup(){
47
48 motor1.setSpeed(50); // in rpm
49 motor2.setSpeed(50); // in rpm
50
51 //Accelstepper Setup
52 accelA.setMaxSpeed(currentMaxSpeed);
53 accelA.setAcceleration(currentAcceleration);
54 accelB.setMaxSpeed(currentMaxSpeed);
55 accelB.setAcceleration(currentAcceleration);
56
57 accelA.setMinPulseWidth(10);
58 accelB.setMinPulseWidth(10);
59
60
61 Serial.begin(9600);
62 digitalWrite(13, HIGH); //turn on LED to indicate program has started
63}
64
65void loop(){
66
67
68 do {
69 // Wenn Daten verfügbar Zeichen in Data schreiben bis 4 Zeichen erreicht oder 0,5 Sekunden Warten nach dem ersten übertragenen byte
70 if (Serial.available()) {
71 if (i == 0)
72 {
73 bewegung = Serial.read();
74 }
75 else
76 {
77 Data[i-1] = Serial.read();
78 }
79 i++;
80 }
81 if(i<1)Zeit = millis();
82 } while (i<4&&(millis()-Zeit) < 500); //nach i< kommt die Anzahl der Zeichen
83 // Serial.flush(); //empty serial buffer
84 // Abschließende Null für gültigen String
85 Data[i-1] = 0;
86
87 schritte = atof(Data); // Wert von String zu Zahl wandeln wenn gewünscht
88 i=0;
89 decodeMessage(bewegung, schritte);
90
91}
92
93void decodeMessage(int msg, int range){
94 int faktor = 5;
95 //check command type and command value
96 if(bitRead(msg, 0) == 1){
97 //Bit 1 = High DOWN (1)
98 // motor1.step(faktor, FORWARD, INTERLEAVE);
99 accelA.move(-range);
100 accelA.runToPosition();
101 }
102 if(bitRead(msg, 1) == 1){
103 //Bit 2 = High UP (2)
104 //motor1.step(faktor, BACKWARD, INTERLEAVE);
105 accelA.move(range);
106 accelA.runToPosition();
107 }
108 if(bitRead(msg, 2) == 1){
109 //Bit 3 = High LEFT (4)
110 motor1.step(faktor, FORWARD, INTERLEAVE);
111 }
112 if(bitRead(msg, 3) == 1){
113 //Bit 4 = High RIGHT (8)
114 motor1.step(faktor, BACKWARD, INTERLEAVE);
115
116 }
117 if((msg & 15) == 0){
118 //Bit 1-4 = Low
119 //sendMsg(000); //send a message back for testing purposes
120 }
121 sendMsg(msg, range);
122}
123
124
125
126void sendMsg(int msg, int range){
127 /* Processing uses Serial.buffer(4) to read the messages it receives,
128 * meaning that messages of 4 bytes long should be sent.
129 * Arduino sends integers as Strings, so to ensure 4 characters are sent
130 * for each message, I check the size of the integer to send and add zeroes
131 * as needed (zeroes ensure that the received message can easily be cast
132 * to an integer by Processing, which would not be the case with other, non-numerical, characters)
133 */
134 //if(Serial.available() > 0) Serial.flush();
135// if(msg < 1000) Serial.print(0);
136// if(msg < 100) Serial.print(0);
137// if(msg < 10) Serial.print(0);
138 //delay(1000);
139
140 Serial.print(range); //...send a confirmation
141 Serial.println(msg);
142
143}
Processing-Code
1import processing.serial.*;
2
3Serial myPort;
4PFont font;
5
6String Schritte = "333";
7int msgQueue[]; //the message queue
8boolean msgLock; //message lock, active until last message is confirmed
9int lstMsg; //last message sent
10int schritt = 125;
11
12void setup(){
13 size(400, 300);
14 background(0);
15 font = createFont("Verdana", 14);
16
17 msgQueue = new int[0];
18
19
20 println(Serial.list());
21 myPort = new Serial(this, Serial.list()[Serial.list().length - 1], 9600); //the highest connected COM port is always my Arduino
22 //myPort.buffer(4); //buffer 4 bytes of data before calling serialEvent()
23 myPort.bufferUntil('\n');
24
25}
26
27void draw(){
28 background(0);
29 textFont(font, 14);
30 text("Taste 8: vorwärts\nTaste 7: weit vorwärts\n\nTaste 2: zurück\nTaste 1: weit zurück\n\n9 -> Schritt erhöhen\n3 -> Schritt verkleinern", 25, 25);
31 text("Schritte: " + schritt, 25, 230);
32 parseQueue();
33}
34
35void keyPressed(){
36 if(int(key) == 50){// Taste 2 DOWN
37 queueMessage(2); //
38 //Schritte = Integer.toString(schritt);
39 queueMessage(schritt);
40 }
41 if(int(key) == 56){// Taste 8 UP
42 queueMessage(1); //
43 //Schritte = Integer.toString(schritt);
44 queueMessage(schritt);
45 }
46 if(int(key) == 51){// Taste 3 Schritt verkleinern
47 schritt = schritt - 5;
48 }
49 if(int(key) == 57){// Taste 9 Schritt erhöhen
50 schritt = schritt + 5;
51 }
52 if(int(key) == 55){ //Taste 7 Grosser Schritt UP
53 queueMessage(1); //
54 queueMessage(600);
55 }
56 if(int(key) == 49){ //Taste 1 Grosser Schritt DOWN
57 queueMessage(2); //
58 queueMessage(600);
59 }
60}
61
62/* serialEvent(Serial myPort)
63 * called when the amount of bytes specified in myPort.buffer()
64 * have been transmitted, converts serial message to integer,
65 * then sets this value in the chair object
66 */
67void serialEvent(Serial myPort){
68 if(myPort.available() > 0){
69
70 String message = myPort.readString(); //read serial buffer
71 int msg = int(message); //convert message to integer
72 println(msgQueue.length);
73 myPort.clear(); //clear whatever might be left in the serial buffer
74 //msgLock = false;
75 if(msg == 0){
76 println("Anweisung durchgeführt");
77 msgLock = false;
78 }
79 }
80}
81
82private void writeSerial(int msg){
83 if(myPort.available() > 0) myPort.clear(); //empty serial buffer before sending
84 myPort.write(msg);
85}
86
87public void queueMessage(int msg){
88 msgQueue = append(msgQueue, msg);
89}
90
91private void parseQueue(){
92
93 if(msgQueue.length > 0 && !msgLock) {
94 msgLock = true; //lock queue, preventing new messages from being sent
95 lstMsg = msgQueue[0]; //queue the first message on the stack
96 writeSerial(lstMsg); // sende richtungsbefehl
97 println("writing Richtung: " + lstMsg);
98
99 msgQueue = subset(msgQueue, 1); // letzten befehl löschen
100
101 lstMsg = msgQueue[0]; //queue the first message on the stack
102 Schritte = Integer.toString(lstMsg);
103 myPort.clear();
104 myPort.write(Schritte);// sende Schrittzahl
105 println("writing Schritte: " + lstMsg);
106
107 msgQueue = subset(msgQueue, 1); // letzten befehl löschen
108 }
109
110}
Knitty: passap Firmware
//////////////////////////////////////////////////////////////////////////////
// Knitty Project
//
// Author: ptflea, schinken
//
//Servo
#include <Servo.h>
Servo servoColour12; // create servo object to control a servo
Servo servoColour34;
#define INT_ENCODER 0
#define INT_IFDR 1
//////////////////////////////////////////////////////////////////////////////
// General purpose definitions
#define PIN_IFDR 3 // Green
#define PIN_CSENSE 2 // Yellow
#define PIN_CREF 4 // White
#define PIN_NEEDLE_RTL 5 // Blue, Pattern RTL
#define PIN_NEEDLE_LTR 6 // , Pattern LTR
#define PIN_BUTTON_1 7 // Button_1 (activate colour change)
#define BUTTONDELAY 20 // delay for Button_1
// PIN 8 and 9 are for the color change servos
#define PIN_Eyelet_1 10 // Eyelet_1 status
#define Eyelet_1_DELAY 100
#define PIN_Eyelet_2 11 // Eyelet_2 status
#define PIN_Eyelet_3 12 // Eyelet_3 status
#define PIN_Eyelet_4 13 // Eyelet_4 status
long buttonLastChecked = 0; // variable to limit the button getting checked every cycle
int button_1_State = 0; // status of button_1
int button_1_Hold = 0; // toggle state of Button_1
long eyelet_1_LastChecked = 0;
int eyelet_1_State = 0;
int eyelet_1_Hold = 0;
#define DIRECTION_UNKNOWN 0
#define DIRECTION_LEFT_RIGHT -1
#define DIRECTION_RIGHT_LEFT 1
char currentDirection = DIRECTION_UNKNOWN;
char lastDirection = DIRECTION_UNKNOWN;
signed int currentCursorPosition = 0;
signed int lastCursorPosition = 0;
signed int leftEndCursorPosition = 0;
unsigned int currentPatternIndex = 0;
signed int firstNeedle = 0;
signed int offsetCarriage_RTL = 52;
signed int offsetCarriage_LTR = 46;
volatile unsigned char knitPattern[255] = {
0};
bool isKnitting = false;
//////////////////////////////////////////////////////////////////////////////
// Knitty Serial Protocol
// Receive commands
#define COM_CMD_PATTERN 'P'
#define COM_CMD_PATTERN_END 'E'
#define COM_CMD_CURSOR 'C'
#define COM_CMD_IFDR 'I'
#define COM_CMD_RESPONSE 'R'
#define COM_CMD_DIRECTION 'D'
#define COM_CMD_DEBUG 'V'
#define COM_CMD_NEW_PATTERN 'N'
#define COM_CMD_FIRST_NEEDLE 'F' //first needle of pattern from right
#define COM_CMD_SEPERATOR ':'
#define COM_CMD_SERVO 'S'
#define COM_CMD_PLOAD_END '\n'
// Parser states
#define COM_PARSE_CMD 0x01
#define COM_PARSE_SEP 0x02
#define COM_PARSE_PLOAD 0x03
unsigned char parserState = COM_PARSE_CMD;
unsigned char parserReceivedCommand = 0;
String parserReceivedPayload = "";
unsigned char patternLength = 0;
void setup() {
Serial.begin(115200);
// Button Input
pinMode(PIN_BUTTON_1, INPUT);
//Eylet Input
pinMode(PIN_Eyelet_1, INPUT);
// Setup PHOTO SENSOR pin change interrupt
pinMode(PIN_CSENSE, INPUT);
pinMode(PIN_CREF, INPUT);
attachInterrupt(INT_ENCODER, interruptPinChangeEncoder, CHANGE);
// Setup IFDR pin change interrupt
pinMode(PIN_IFDR, INPUT);
attachInterrupt(INT_IFDR, interruptPinChangeIfdr, FALLING);
// Setup Needles
pinMode(PIN_NEEDLE_RTL, OUTPUT);
digitalWrite(PIN_NEEDLE_RTL, HIGH);
pinMode(PIN_NEEDLE_LTR, OUTPUT);
digitalWrite(PIN_NEEDLE_LTR, HIGH);
}
void executeCommand(unsigned char cmd, String payload) {
switch(cmd) {
case COM_CMD_PATTERN:
patternLength = payload.length();
for(unsigned char i = 0; i < patternLength; i++) {
knitPattern[i] = (payload.charAt(i) == '1')? 1 : 0;
}
break;
case COM_CMD_CURSOR:
currentCursorPosition = payload.toInt();
break;
case COM_CMD_FIRST_NEEDLE:
firstNeedle = payload.toInt()*2-2;
break;
case COM_CMD_SERVO:
switch(payload.toInt()) {
case 0: //no colour selected
servoColour12.write(90);
servoColour34.write(90);
break;
case 1: //Color 1
servoColour12.write(70);
servoColour34.write(90);
break;
case 2: //Color 2
servoColour12.write(115);
servoColour34.write(90);
break;
case 3: //Color 3
servoColour12.write(90);
servoColour34.write(70);
break;
case 4: //Color 4
servoColour12.write(90);
servoColour34.write(115);
break;
case 5: //Servo off
servoColour12.detach();
servoColour34.detach();
break;
case 6: //Servo on
servoColour12.attach(8);
servoColour34.attach(9);
break;
}
break;
}
}
void sendCommand(unsigned char cmd, String payload) {
Serial.write(cmd);
Serial.write(COM_CMD_SEPERATOR);
Serial.print(payload);
Serial.write("\n");
}
void parserSerialStream() {
if (Serial.available() == 0) {
return;
}
char buffer = Serial.read();
switch(parserState) {
case COM_PARSE_CMD:
parserState = COM_PARSE_SEP;
parserReceivedCommand = buffer;
parserReceivedPayload = "";
break;
case COM_PARSE_SEP:
// We're awaiting a seperator here, if not, back to cmd
if(buffer == COM_CMD_SEPERATOR) {
parserState = COM_PARSE_PLOAD;
break;
}
parserState = COM_PARSE_CMD;
break;
case COM_PARSE_PLOAD:
if(buffer == COM_CMD_PLOAD_END) {
executeCommand(parserReceivedCommand, parserReceivedPayload);
parserState = COM_PARSE_CMD;
sendCommand(COM_CMD_RESPONSE, "OK");
break;
}
parserReceivedPayload += buffer;
break;
}
}
void loop() {
parserSerialStream();
//check if button for colour change ist activated and send response to processing
button_1_State = digitalRead(PIN_BUTTON_1);
if( buttonLastChecked == 0 ) // see if this is the first time checking the buttons
buttonLastChecked = millis()+BUTTONDELAY; // force a check this cycle
if( millis() - buttonLastChecked > BUTTONDELAY ) { // make sure a reasonable delay passed
if (button_1_State == HIGH) {
if (button_1_Hold == HIGH) {
// Send
sendCommand(COM_CMD_RESPONSE, "ON");
button_1_Hold = LOW;
}
}
else {
if (button_1_Hold == LOW) {
// Send
sendCommand(COM_CMD_RESPONSE, "OFF");
button_1_Hold = HIGH;
}
}
buttonLastChecked = millis(); // reset the lastChecked value
}
//check Eyelets
eyelet_1_State = digitalRead(PIN_Eyelet_1);
if( eyelet_1_LastChecked == 0 ) // see if this is the first time checking the buttons
eyelet_1_LastChecked = millis()+Eyelet_1_DELAY; // force a check this cycle
if( millis() - eyelet_1_LastChecked > Eyelet_1_DELAY ) { // make sure a reasonable delay passed
if (eyelet_1_State == HIGH) {
if (eyelet_1_Hold == HIGH) {
// Send
sendCommand(COM_CMD_RESPONSE, "Eyelet 1 OUT");
eyelet_1_Hold = LOW;
}
}
else {
if (eyelet_1_Hold == LOW) {
// Send
sendCommand(COM_CMD_RESPONSE, "Eyelet 1 IN");
eyelet_1_Hold = HIGH;
}
}
eyelet_1_LastChecked = millis(); // reset the lastChecked value
}
}
void setNeedleByCursor(char cursorPosition) {
// Just to be sure that we never exceed the pattern
if(cursorPosition > patternLength-1 || cursorPosition < 0) {
return;
}
if(currentDirection == DIRECTION_LEFT_RIGHT) {
setNeedle_LTR(knitPattern[cursorPosition]);
}
else if(currentDirection == DIRECTION_RIGHT_LEFT) {
setNeedle_RTL(knitPattern[patternLength-cursorPosition-1]);
}
}
void setNeedle_RTL(char state) {
//change state because the E6000 sets needle by 0
if(state==1){
state = 0;
}
else
{
state = 1;
}
digitalWrite(PIN_NEEDLE_RTL, state);
}
void setNeedle_LTR(char state) {
//change state because the E6000 sets needle by 0
if(state==1){
state = 0;
}
else
{
state = 1;
}
digitalWrite(PIN_NEEDLE_LTR, state);
}
void interruptPinChangeEncoder() {
char currentPinChangeValue = digitalRead(PIN_CSENSE);
char currentPinChangeOppositeValue = digitalRead(PIN_CREF);
// Determine direction
if(currentPinChangeValue == currentPinChangeOppositeValue) {
currentDirection = DIRECTION_LEFT_RIGHT;
}
else {
currentDirection = DIRECTION_RIGHT_LEFT;
}
// RTL = 1, LTR = -1
currentCursorPosition += currentDirection;
//store last position
lastCursorPosition = currentCursorPosition;
//debug cursorposition
//sendCommand(COM_CMD_RESPONSE, String(currentCursorPosition));
// Check if we're in range of our needles
if((currentDirection == DIRECTION_RIGHT_LEFT && currentCursorPosition > offsetCarriage_RTL + firstNeedle) ||
(currentDirection == DIRECTION_LEFT_RIGHT && currentCursorPosition - offsetCarriage_LTR <= patternLength + firstNeedle)) {
if(currentPatternIndex > patternLength) {
setNeedle_RTL(0);
setNeedle_LTR(0);
currentPatternIndex = 0;
isKnitting = false;
sendCommand(COM_CMD_PATTERN_END, "1");
}
else {
if(isKnitting == true) {
// React on FALLING Edge
if(currentPinChangeValue == 1) {
setNeedleByCursor(currentPatternIndex);
currentPatternIndex++;
}
}
}
}
if(lastDirection != currentDirection) {
lastDirection = currentDirection;
currentPatternIndex = 0;
isKnitting = true;
if(currentDirection == DIRECTION_RIGHT_LEFT) {
sendCommand(COM_CMD_DIRECTION, "RTL");
}
else {
sendCommand(COM_CMD_DIRECTION, "LTR");
}
}
}
// We only use the IFDR to determine if we can send the pattern
// for the next line.
void interruptPinChangeIfdr() {
if(isKnitting == false) {
sendCommand(COM_CMD_IFDR, "1");
}
}