Germany
Offline
Newbie
Karma: 0
Posts: 32
|
 |
« on: December 20, 2012, 05:56:04 pm » |
Hi there, im in the middle of a small project. For that project i have a stepper unit consisting out of two steppers, one uln2803, and two Attiny45. (ofcourse an arduino  ) My problem is: I wanna drive one stepper with one attiny. This uses 4 pins. So scratch 4 of the five pins. Theres only one pin left for commuication from the arduino to the attiny. I wanned to use the softwareserial library for that on the attiny. But theres a problem, i have to declare a RX and a TX pin, but i only have room for my RX pin. I found a version of the SoftwareSerial library, which only uses a TX pin, but not one that only recieves. (librarie can be fund in THIS post.) Sadly i cant moddify the library myself, because i dont fully understand how those work. Has anyone some tipps / a solution for me? - Robohac
|
|
|
|
« Last Edit: December 20, 2012, 05:57:56 pm by Robohac »
|
Logged
|
|
|
|
|
Netherlands
Online
Tesla Member
Karma: 91
Posts: 9446
In theory there is no difference between theory and practice, however in practice there are many...
|
 |
« Reply #1 on: December 21, 2012, 04:47:34 am » |
IIRC, you can use the standard SoftSerial library and declare the pin you do not want to use as pin -1.
give it a try.
|
|
|
|
|
Logged
|
|
|
|
|
Germany
Offline
Newbie
Karma: 0
Posts: 32
|
 |
« Reply #2 on: December 21, 2012, 11:56:49 am » |
Ok so i wrote the first bit of code. One problem though: It dosnt work  but im tired and just wanna show what ive done so far (ill correct the mistakes tomorrow) I think the mistake is in the function stringtonumber(). // Modes: // R (Rotate) format: R<Ticks>;<Speed>; // S (Spinn) format: S<Speed>;<Time>; // C (Constant) format: C<r/l>;<Speed>;
#include <SoftwareSerial.h>
//declare variables for the motor pins int motorPin1 = 3; // Blue - 28BYJ48 pin 1 int motorPin2 = 4; // Pink - 28BYJ48 pin 2 int motorPin3 = 2; // Yellow - 28BYJ48 pin 3 int motorPin4 = 1; // Orange - 28BYJ48 pin 4 // Red - 28BYJ48 pin 5 (VCC) int rxPin = 0; //Serial recieve pin int motorSpeed = 0; //variable to set stepper speed
SoftwareSerial mySerial(rxPin, -1); // RX, TX
String cue = "";
void setup() { //declare the motor pins as outputs pinMode(motorPin1, OUTPUT); pinMode(motorPin2, OUTPUT); pinMode(motorPin3, OUTPUT); pinMode(motorPin4, OUTPUT);
}
void loop() { while (mySerial.available()>0) { cue = cue + getData(); } switch (cue.charAt(0)) { case 'R': rotate(); break; case 'S': spinn(); break; case 'C': constant(); break; } }
void counterclockwise (){ // 1 digitalWrite(motorPin1, HIGH); digitalWrite(motorPin2, LOW); digitalWrite(motorPin3, LOW); digitalWrite(motorPin4, LOW); delay(motorSpeed); // 2 digitalWrite(motorPin1, HIGH); digitalWrite(motorPin2, HIGH); digitalWrite(motorPin3, LOW); digitalWrite(motorPin4, LOW); delay (motorSpeed); // 3 digitalWrite(motorPin1, LOW); digitalWrite(motorPin2, HIGH); digitalWrite(motorPin3, LOW); digitalWrite(motorPin4, LOW); delay(motorSpeed); // 4 digitalWrite(motorPin1, LOW); digitalWrite(motorPin2, HIGH); digitalWrite(motorPin3, HIGH); digitalWrite(motorPin4, LOW); delay(motorSpeed); // 5 digitalWrite(motorPin1, LOW); digitalWrite(motorPin2, LOW); digitalWrite(motorPin3, HIGH); digitalWrite(motorPin4, LOW); delay(motorSpeed); // 6 digitalWrite(motorPin1, LOW); digitalWrite(motorPin2, LOW); digitalWrite(motorPin3, HIGH); digitalWrite(motorPin4, HIGH); delay (motorSpeed); // 7 digitalWrite(motorPin1, LOW); digitalWrite(motorPin2, LOW); digitalWrite(motorPin3, LOW); digitalWrite(motorPin4, HIGH); delay(motorSpeed); // 8 digitalWrite(motorPin1, HIGH); digitalWrite(motorPin2, LOW); digitalWrite(motorPin3, LOW); digitalWrite(motorPin4, HIGH); delay(motorSpeed); }
void clockwise(){ // 1 digitalWrite(motorPin4, HIGH); digitalWrite(motorPin3, LOW); digitalWrite(motorPin2, LOW); digitalWrite(motorPin1, LOW); delay(motorSpeed); // 2 digitalWrite(motorPin4, HIGH); digitalWrite(motorPin3, HIGH); digitalWrite(motorPin2, LOW); digitalWrite(motorPin1, LOW); delay (motorSpeed); // 3 digitalWrite(motorPin4, LOW); digitalWrite(motorPin3, HIGH); digitalWrite(motorPin2, LOW); digitalWrite(motorPin1, LOW); delay(motorSpeed); // 4 digitalWrite(motorPin4, LOW); digitalWrite(motorPin3, HIGH); digitalWrite(motorPin2, HIGH); digitalWrite(motorPin1, LOW); delay(motorSpeed); // 5 digitalWrite(motorPin4, LOW); digitalWrite(motorPin3, LOW); digitalWrite(motorPin2, HIGH); digitalWrite(motorPin1, LOW); delay(motorSpeed); // 6 digitalWrite(motorPin4, LOW); digitalWrite(motorPin3, LOW); digitalWrite(motorPin2, HIGH); digitalWrite(motorPin1, HIGH); delay (motorSpeed); // 7 digitalWrite(motorPin4, LOW); digitalWrite(motorPin3, LOW); digitalWrite(motorPin2, LOW); digitalWrite(motorPin1, HIGH); delay(motorSpeed); // 8 digitalWrite(motorPin4, HIGH); digitalWrite(motorPin3, LOW); digitalWrite(motorPin2, LOW); digitalWrite(motorPin1, HIGH); delay(motorSpeed); }
String getData() { String input = ""; while(mySerial.available()>0) { input = input + mySerial.read(); } return input; }
void deleteOld() { if(cue.length() != 0) { int n = 1; for (n = 1; n < cue.length(); n++) { if (cue.charAt(n) == ';') { break; } } cue = cue.substring(n + 1); } }
void rotate() { }
void spinn() { }
void constant() { char direct = cue.charAt(1); int paramlength = 0; for (paramlength = 3; paramlength < cue.length(); paramlength++) { if (cue.charAt(paramlength) == ';') { break; } } paramlength = paramlength - 3; motorSpeed = stringtonumber(cue.substring(3, paramlength + 3)); if (direct == 'r') { while (mySerial.available()==0) { clockwise(); } } else { while (mySerial.available()==0) { counterclockwise(); } } deleteOld(); }
int stringtonumber(String snumber) { int number = 0; for (int z = 0; z < snumber.length(); z++) { number = (number*10) + (snumber.charAt(z) - 48); } return number; }
|
|
|
|
|
Logged
|
|
|
|
|
UK
Offline
Tesla Member
Karma: 89
Posts: 6406
-
|
 |
« Reply #3 on: December 21, 2012, 12:17:26 pm » |
You don't say what's wrong, but the way you're receiving the command string looks unsafe to me.
Firstly, you using the String class, which isn't giving you any benefit here and introduces the possibility of memory leaks and resulting stability problems.
Secondly, you aren't waiting until the whole command string is available before you try to parse it.
It would make far more sense to accumulate the incoming chars in a char array until you recognise the terminating ';' and then process the whole command.
As far as SoftwareSerial goes, you need to arrange for the SoftwareSerial to have a zero value for _transmitBitMask. This value is looked up in a board-specific way from the pin number you supply and I don't know whether there are any pin numbers that translate to zero. You could always call digitalPinToBitMask() with a few pin numbers and see whether any came back with zero. If you find any that do, you could use that as your TX pin. Otherwise, I suppose you could modify SoftwareSerial::setTX() and SoftwareSerial::setRX() to test the supplied pin number and set the port and bitmask properties to zero if an out-of-range value was supplied.
|
|
|
|
|
Logged
|
|
|
|
|
Queens, New York
Online
Edison Member
Karma: 29
Posts: 1589
"Of all the things I've ever lost, I miss my mind the most" -Ozzy Osbourne
|
 |
« Reply #4 on: December 21, 2012, 12:19:59 pm » |
Do you need to use pins 0 and 1 or can you possibly move somethings around. The easiest way of solving your problem is to see what goes in and what comes out. However, you would need the serial monitor for that, meaning the Tx pin. int stringtonumber(String snumber) { int number = 0; for (int z = 0; z < snumber.length(); z++) { number = (number*10) + (snumber.charAt(z) - 48); Serial.print(snumber); Serial.print(", "); Serial.println(number); } return number; }
|
|
|
|
« Last Edit: December 21, 2012, 12:27:50 pm by HazardsMind »
|
Logged
|
UNO, MEGA, NANO, 4x4 keypad, micro servos, RF transceivers, bluetooth, ultrasonic sensor, 20x4 I2C LCD, 3.2 TFT touch screen, L298N Dual motor driver, Voice Recognition 15W, Gameduino
Arduino Tutorials, coming soon.
"If your doing nothing, it does not mean your lazy, it just means your open for anything that suits you" - Unknown
|
|
|
|
Queens, New York
Online
Edison Member
Karma: 29
Posts: 1589
"Of all the things I've ever lost, I miss my mind the most" -Ozzy Osbourne
|
 |
« Reply #5 on: December 21, 2012, 12:24:24 pm » |
Mine is quite simular to yours, in function, but much more simpler. Look at how I get my data, and split it. /* control test */ #include<string.h> int DRV1,DRV2,STRR,STRL; int x = 0; int y = 0; int s = 0; void move(int x = 0,int y = 0,int s = 0); //double z; String val = ""; String X= ""; String Y= ""; String state = ""; //int state = 0; int currentCommand = 0;
int ledpin = 13; byte Mopen = 4; byte Mclosed = 2; byte M1L = 3;// PWM byte M2L = 5;// PWM byte M1R = 9;// PWM byte M2R = 6;// PWM
void setup() { pinMode(ledpin, OUTPUT); // pin 13 (on-board LED) as OUTPUT pinMode(Mopen, OUTPUT); pinMode(Mclosed, OUTPUT); pinMode(M1L, OUTPUT); pinMode(M1R, OUTPUT); pinMode(M2L, OUTPUT); pinMode(M2R, OUTPUT); Serial.begin(9600); // start serial communication at 115200bps
}
void loop() { if( Serial.available()) // if data is available to read { digitalWrite(ledpin, HIGH); char c= Serial.read(); if (c == ','){ //look at the incoming chars, if it is a ',' then switch the case currentCommand++; } else { //if it is not ',' then store chars in string val += c; //Serial.println(val); switch (currentCommand) {
case 0: X += val; val = ""; break; case 1: Y += val; val = ""; break;
case 2: //Serial.println("X: "+X); //Serial.println("Y: "+Y); state = val; // this will only receive 1 value currentCommand = 0; val = ""; //Serial.println("state: "+state); //Serial.println(); x=X.toInt(); //string to int y=Y.toInt(); //string to int s=state.toInt(); //string to int X=""; Y=""; state=""; move(x, y, s); break; } } } } void move(int x, int y, int s) { x=constrain(x, -90, 90); y=constrain(y, -90, 90);
//Movement varibles int DRV2 = map(x, -90, 0, 255, 0); int DRV1 = map(x, 0, 90, 0, 255); int STRR = map(y, -90, 0, 255, 0); int STRL = map(y, 0, 90, 0, 255);
if(x > 0)//forwards { //Serial.println("Driving"); analogWrite(M1L, abs(DRV1 - STRL)); analogWrite(M1R, abs(DRV1 - STRR)); analogWrite(M2L, 0); analogWrite(M2R, 0); } else if(x < 0)//backwards { //Serial.println("Driving"); analogWrite(M1L, 0); analogWrite(M1R, 0); analogWrite(M2L, abs(DRV2 - STRR)); analogWrite(M2R, abs(DRV2 - STRL)); } else if(x == 0 && y >0)//right { //Serial.println("Driving"); analogWrite(M1L, STRL); analogWrite(M1R, 0); analogWrite(M2L, 0); analogWrite(M2R, STRL); } else if(x == 0 && y < 0)//left { //Serial.println("Driving"); analogWrite(M1L, 0); analogWrite(M1R, STRR); analogWrite(M2L, STRR); analogWrite(M2R, 0); }
else //full stop { digitalWrite(M1L, LOW); digitalWrite(M1R, LOW); digitalWrite(M2L, LOW); digitalWrite(M2R, LOW); }
if(s == 1) { //Serial.println("Claw Opening"); digitalWrite(Mopen, HIGH); digitalWrite(Mclosed, LOW); } if(s == 2) { //Serial.println("Claw Closing"); digitalWrite(Mopen, LOW); digitalWrite(Mclosed, HIGH); } if(s == 0) { digitalWrite(Mopen, LOW); digitalWrite(Mclosed, LOW); } else{ digitalWrite(ledpin, LOW); x=0; y=0; s=0; } }
Your more than welcome to modify this and use it.
|
|
|
|
« Last Edit: December 21, 2012, 12:32:21 pm by HazardsMind »
|
Logged
|
UNO, MEGA, NANO, 4x4 keypad, micro servos, RF transceivers, bluetooth, ultrasonic sensor, 20x4 I2C LCD, 3.2 TFT touch screen, L298N Dual motor driver, Voice Recognition 15W, Gameduino
Arduino Tutorials, coming soon.
"If your doing nothing, it does not mean your lazy, it just means your open for anything that suits you" - Unknown
|
|
|
|
Seattle, WA USA
Offline
Brattain Member
Karma: 316
Posts: 35593
Seattle, WA USA
|
 |
« Reply #6 on: December 22, 2012, 09:34:55 am » |
My problem is: I wanna drive one stepper with one attiny. This uses 4 pins. So scratch 4 of the five pins. Using a stepper driver board to do the hard work only requires two pins - one to set the direction and one to cause a step. Save two pins.
|
|
|
|
|
Logged
|
|
|
|
|
Germany
Offline
Newbie
Karma: 0
Posts: 32
|
 |
« Reply #7 on: December 22, 2012, 09:50:11 am » |
Wow, thank you for your response  @HazardsMind Ill read trough your code shortly, and see how i can optimize mine @PeterH I use strings because it was the first thing which came in my mind. Thank you for your hint, that i wasnt wayting for the whole string. I fixet that. Current state of the programm (The functions wor now, i testet them on an arduino but not all are finished, because i want to test them one by one to prevent mistakes) // Modes: // R (Rotate) format: R<Ticks>,<Speed>; // S (Spinn) format: S<Speed>,<Time>; // C (Constant) format: C<r/l><Speed>;
#include <SoftwareSerial.h>
//declare variables for the motor pins int motorPin1 = 3; // Blue - 28BYJ48 pin 1 int motorPin2 = 4; // Pink - 28BYJ48 pin 2 int motorPin3 = 2; // Yellow - 28BYJ48 pin 3 int motorPin4 = 1; // Orange - 28BYJ48 pin 4 // Red - 28BYJ48 pin 5 (VCC)
int rxPin = 0; //Serial recieve pin
int motorSpeed = 0; //variable to set stepper speed
SoftwareSerial mySerial(rxPin, -1); // RX, TX
String cue = "";
void setup() { //declare the motor pins as outputs pinMode(motorPin1, OUTPUT); pinMode(motorPin2, OUTPUT); pinMode(motorPin3, OUTPUT); pinMode(motorPin4, OUTPUT);
}
void loop() { getData(); switch (cue.charAt(0)) { case 'R': rotate(); break; case 'S': spinn(); break; case 'C': constant(); break; } }
void rotate() { // R (Rotate) format: R<Ticks>,<Speed>; }
void spinn() { // S (Spinn) format: S<Speed>,<Time>; }
void constant() { // C (Constant) format: C<r/l><Speed>; String smotorSpeed; for (int i = 0; i < cue.length(); i++) { if (cue.charAt(i) == ';') { break; } else { smotorSpeed.concat(cue.charAt(i)); } } motorSpeed = stringtonumber(smotorSpeed); if(cue.charAt(1) == 'r') { while(true) { clockwise(); if(mySerial.available()) { break; } } } else { while(true) { counterclockwise(); if(mySerial.available()) { break; } } } deleteOld(); }
void getData() { char character; while(true) { if (mySerial.available() > 0) { character = mySerial.read(); cue.concat(mySerial.read()); if (cue.charAt(cue.length() - 1) == ';') { break; } } } }
int stringtonumber(String snumber) { int number = 0; for (int z = 0; z < snumber.length(); z++) { number = (number*10) + (snumber.charAt(z) - 48); } return number; }
void counterclockwise (){ // 1 digitalWrite(motorPin1, HIGH); digitalWrite(motorPin2, LOW); digitalWrite(motorPin3, LOW); digitalWrite(motorPin4, LOW); delay(motorSpeed); // 2 digitalWrite(motorPin1, HIGH); digitalWrite(motorPin2, HIGH); digitalWrite(motorPin3, LOW); digitalWrite(motorPin4, LOW); delay (motorSpeed); // 3 digitalWrite(motorPin1, LOW); digitalWrite(motorPin2, HIGH); digitalWrite(motorPin3, LOW); digitalWrite(motorPin4, LOW); delay(motorSpeed); // 4 digitalWrite(motorPin1, LOW); digitalWrite(motorPin2, HIGH); digitalWrite(motorPin3, HIGH); digitalWrite(motorPin4, LOW); delay(motorSpeed); // 5 digitalWrite(motorPin1, LOW); digitalWrite(motorPin2, LOW); digitalWrite(motorPin3, HIGH); digitalWrite(motorPin4, LOW); delay(motorSpeed); // 6 digitalWrite(motorPin1, LOW); digitalWrite(motorPin2, LOW); digitalWrite(motorPin3, HIGH); digitalWrite(motorPin4, HIGH); delay (motorSpeed); // 7 digitalWrite(motorPin1, LOW); digitalWrite(motorPin2, LOW); digitalWrite(motorPin3, LOW); digitalWrite(motorPin4, HIGH); delay(motorSpeed); // 8 digitalWrite(motorPin1, HIGH); digitalWrite(motorPin2, LOW); digitalWrite(motorPin3, LOW); digitalWrite(motorPin4, HIGH); delay(motorSpeed); }
void clockwise(){ // 1 digitalWrite(motorPin4, HIGH); digitalWrite(motorPin3, LOW); digitalWrite(motorPin2, LOW); digitalWrite(motorPin1, LOW); delay(motorSpeed); // 2 digitalWrite(motorPin4, HIGH); digitalWrite(motorPin3, HIGH); digitalWrite(motorPin2, LOW); digitalWrite(motorPin1, LOW); delay (motorSpeed); // 3 digitalWrite(motorPin4, LOW); digitalWrite(motorPin3, HIGH); digitalWrite(motorPin2, LOW); digitalWrite(motorPin1, LOW); delay(motorSpeed); // 4 digitalWrite(motorPin4, LOW); digitalWrite(motorPin3, HIGH); digitalWrite(motorPin2, HIGH); digitalWrite(motorPin1, LOW); delay(motorSpeed); // 5 digitalWrite(motorPin4, LOW); digitalWrite(motorPin3, LOW); digitalWrite(motorPin2, HIGH); digitalWrite(motorPin1, LOW); delay(motorSpeed); // 6 digitalWrite(motorPin4, LOW); digitalWrite(motorPin3, LOW); digitalWrite(motorPin2, HIGH); digitalWrite(motorPin1, HIGH); delay (motorSpeed); // 7 digitalWrite(motorPin4, LOW); digitalWrite(motorPin3, LOW); digitalWrite(motorPin2, LOW); digitalWrite(motorPin1, HIGH); delay(motorSpeed); // 8 digitalWrite(motorPin4, HIGH); digitalWrite(motorPin3, LOW); digitalWrite(motorPin2, LOW); digitalWrite(motorPin1, HIGH); delay(motorSpeed); }
void deleteOld() { if(cue.length() != 0) { int n = 1; for (n = 1; n < cue.length(); n++) { if (cue.charAt(n) == ';') { break; } } cue = cue.substring(n + 1); } }
As i wanted to test it on my Attiny45 i rann into the problem of compiling it (Arduino 1.0.1 following THIS tutorial). The reason: 6.372 Bytes is the size of the compiled sketch. Attiny45 has only 4  so ill get an 85, it has 8k memmory. Seems like SoftwareSerial is quite a big library
|
|
|
|
|
Logged
|
|
|
|
|
Germany
Offline
Newbie
Karma: 0
Posts: 32
|
 |
« Reply #8 on: December 22, 2012, 09:52:46 am » |
@PaulS Jeah that probably would be easyer, but i have the parts, and a stepperboard costs more than 4€ per stepper. My parts were about 2,50€ so jeah  (i had thos flying around)
|
|
|
|
|
Logged
|
|
|
|
|
UK
Offline
Tesla Member
Karma: 89
Posts: 6406
-
|
 |
« Reply #9 on: December 22, 2012, 10:03:14 am » |
The reason: 6.372 Bytes is the size of the compiled sketch. Attiny45 has only 4  so ill get an 85, it has 8k memmory. Seems like SoftwareSerial is quite a big library Do you know how much of that size is taken up by SoftwareSerial? I don't know whether you'd be able to save enough to bring it down to 4K, but there's some pretty repetitive code there and I suspect it would be possible to reduce the size a bit. Worth a try if you're keen to stick with the existing chip.
|
|
|
|
|
Logged
|
|
|
|
|
United Kingdom
Online
Faraday Member
Karma: 131
Posts: 4693
|
 |
« Reply #10 on: December 22, 2012, 10:18:46 am » |
I've just done some measurements using the standard Arduino core:
Core (running an empty program): 490 bytes pinMode and digitalWrite: 864 bytes SoftwareSerial library: 2114 bytes String library: 1500 bytes
You could save the 864 bytes and more if you use direct port access, and you could save most of the 1500 bytes if you didn't use String (which is a bad thing to use anyway). You could save some of the SoftwareSerial code if you removed the transmit code and used a fixed baud rate. So I think it's possible to get your program to fit in an Attiny45.
For Attiny mcus, I write the programs in AVR Studio, copying code from the Arduino core and library as and when I need it. That way, I avoid having unnecessary code from the core as well.
|
|
|
|
|
Logged
|
Formal verification of safety-critical software, software development, and electronic design and prototyping. http://www.eschertech.com
|
|
|
|
Queens, New York
Online
Edison Member
Karma: 29
Posts: 1589
"Of all the things I've ever lost, I miss my mind the most" -Ozzy Osbourne
|
 |
« Reply #11 on: December 22, 2012, 11:56:30 am » |
You should maybe look into direct port manipulation for your stepper motors. It may shave off some of that high memory usage, which is good.
|
|
|
|
|
Logged
|
UNO, MEGA, NANO, 4x4 keypad, micro servos, RF transceivers, bluetooth, ultrasonic sensor, 20x4 I2C LCD, 3.2 TFT touch screen, L298N Dual motor driver, Voice Recognition 15W, Gameduino
Arduino Tutorials, coming soon.
"If your doing nothing, it does not mean your lazy, it just means your open for anything that suits you" - Unknown
|
|
|
|
Netherlands
Online
Tesla Member
Karma: 91
Posts: 9446
In theory there is no difference between theory and practice, however in practice there are many...
|
 |
« Reply #12 on: December 22, 2012, 12:48:09 pm » |
You could save some of the SoftwareSerial code if you removed the transmit code and used a fixed baud rate. I removed the lookuptables and replaced them with formulas => ~190 bytes saved from the SWserial - http://arduino.cc/forum/index.php/topic,138497.0.html -
|
|
|
|
|
Logged
|
|
|
|
|
Germany
Offline
Newbie
Karma: 0
Posts: 32
|
 |
« Reply #13 on: December 22, 2012, 05:51:06 pm » |
@ dc42 ho would you get rid of strings? should i use char arrays? i think that would make the code much mor complicated, because you constantly have to change the array size.
|
|
|
|
|
Logged
|
|
|
|
|
UK
Offline
Tesla Member
Karma: 89
Posts: 6406
-
|
 |
« Reply #14 on: December 22, 2012, 06:05:35 pm » |
@ dc42 ho would you get rid of strings? should i use char arrays? i think that would make the code much mor complicated, because you constantly have to change the array size.
No, you just make it big enough to cope with all the expected situations, and check to prevent it from overflowing in unexpected situations.
|
|
|
|
|
Logged
|
|
|
|
|
|