14. Interface and application programming¶
This week I worked on making an application for the machine that kids in FabLab Armenia made at machine building week.
Group Assignment¶
We got acquainted with G4P GUI Builder and Visual Studio, C#, which you can see in our group page
At first Shushan told about C#, introduced it to us. And her example of making software by this one was Turning On and Off Led.
After Rudolf introduced us G4P GUI Builder.
Individual Assignment¶
Machine, that was built by kids and instructors in FabLab Armenia, there were already programmed electronics (by Arduino board).
So it was easier for me to work on the existing code and making software.
I used Visual Studio, C# for building my program.
After uploading it and setting it up, I create a new project and chose Windows Forms App (.NET Framework) as you can see in photo below. It’s a project for creating an application with a Windows Forms user interface.
After I just saved it in folder and started my work.
This will be the interface in which we will create our buttons.
The very first thins is SerialPort. And by RightClicking you can go to Properties. In the opened window on right side you will choose BaudRate and Port Name which you can look at in your Arduino IDE port, while you connect your board to you laptop. Mine was COM10.
After, by going to View >> Code , you will see the code, in which you have to type
serialPort1.Open();
In ToolBox I found buttons that I needed, and set them in the properties by which color, font, sizes I wanted.
serialPort1.Write("p");
Here is the tool for Starting program that I made.
I forgot to connect my board after starting the program that I build, so this was the main error.
After is the program, that was ran.
By comparing with the existing code, I started to write a code which will work with C#.
PLay, Stop and Autohome buttons¶
#define DIR_PIN 3
#define STEP_PIN 2
#define EN_PIN 4
#define RIGHT_PIN 8
#define LEFT_PIN 7
#define stepsPerRevolution 5000
String data;
char d1;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
pinMode(EN_PIN, OUTPUT);
digitalWrite(EN_PIN, HIGH); // Deactivate driver (LOW active)
pinMode(DIR_PIN, OUTPUT);
digitalWrite(DIR_PIN, LOW); // LOW or HIGH
pinMode(STEP_PIN, OUTPUT);
digitalWrite(STEP_PIN, LOW);
digitalWrite(EN_PIN, LOW); // Activate driver
pinMode(RIGHT_PIN, INPUT_PULLUP);
pinMode(LEFT_PIN, INPUT_PULLUP);
}
void loop() {
int button_Left = digitalRead(LEFT_PIN);
int button_Right = digitalRead(RIGHT_PIN);
if (Serial.available()){
data = Serial.readString();
d1 = data.charAt(0);
if(d1 == 'p'){
digitalWrite(DIR_PIN, HIGH);
for (int i =1; i <= 1000000; i++) {
digitalWrite(STEP_PIN, HIGH);
delayMicroseconds(500000/stepsPerRevolution);
digitalWrite(STEP_PIN, LOW);
delayMicroseconds(500000/stepsPerRevolution);
button_Left = digitalRead(LEFT_PIN);
button_Right = digitalRead(RIGHT_PIN);
if (button_Left == 0){
digitalWrite(DIR_PIN,LOW);
// break;
} if (button_Right == 0) {
digitalWrite(DIR_PIN, HIGH);
// break;
}
if (Serial.available()){
data = Serial.readString();
d1 = data.charAt(0);
if(d1 == 's'){
break;
}
}
}
}
else if (d1 == 'a') {
digitalWrite(DIR_PIN, HIGH);
for (int i =1; i <= 1000000; i++) {
digitalWrite(STEP_PIN, HIGH);
delayMicroseconds(500000/stepsPerRevolution);
digitalWrite(STEP_PIN, LOW);
delayMicroseconds(500000/stepsPerRevolution);
button_Left = digitalRead(LEFT_PIN);
// int button_Right = digitalRead(RIGHT_PIN);
if (button_Left == 0){
break;
}
}
}
}
}
In this code you can see, that in void loop() I first write to check if there is any data available on the serial communication port. If there is data available, it reads the data using Serial.readString() and stores it in the variable data. It then extracts the first character of the received data and assigns it to d1.
If the first character received (d1) is ‘p’ (play), then it sets the direction pin (DIR_PIN) to HIGH. Enters a loop that runs 1,000,000 milliseconds. >> Reads the state of two buttons (LEFT_PIN and RIGHT_PIN) to check if they are pressed. >> If the left/right button is pressed (button_Left/Right == 0), it changes the direction by setting DIR_PIN to LOW. >> Continues to check for additional serial data (Serial.available()) and stops the motor if the received character is ‘s’ (stop).
Also there’s the Autohome function. If the received character (d1) is ‘a’ (autohome), motor is doing the same as in ‘play’, but if the left button is pressed (button_Left == 0), it breaks out of the loop, stopping the motor.
And after I sent this code to Arduino board.
I also added a scroll bar, track bar so that the moving part of our machine could change it’s speed and position.
For slider I made the maximum and minimum numbers, that it can give. It was 0, 1 and 2. Large Change is the ize of the slider button.
Also by clicking once on this buttons below, you can change the font, size, color, style of the button.
And here what I’ve got.
After I checked, if the scroll bars are working, and which numbers they give, so that I could write the receiving code in Arduino IDE.
For that I used code
private void b_Scroll(object sender, ScrollEventArgs e)
{
MessageBox.Show(b, ValueTuple.ToString());
serialPort1.Write("b"+ b.Value.ToString());
}
So after playing the program I checked and it worked.
Here is the Position scroll bar which has worked.
Position and Speed¶
So after I started editing my previous code by adding position and speed.
I set new integers and not only.
const int stepsPerRevolution = 32260 ; // = 4033*8 - how much microrotations it does
const int length = 805; // mm
int microrotatePermm = stepsPerRevolution / length; // microrotatePermm - one microrotation for 1mm
int microstep = 1600; // number of microsteps per full revolution
int microrotatePer1mms = 1000000 / microrotatePermm ; // in 1mm/sec microrotations number
int microrotatePerPartmms = microrotatePer1mms / 2 ; // second/2 / microstep
int speed = 120; // 50 mm/sec speed start , by default
After I made functions so my code will be more tidy and understandable.
void play () {
button_Left = digitalRead(LEFT_PIN);
button_Right = digitalRead(RIGHT_PIN);
digitalWrite(DIR_PIN, HIGH);
for (int i =1; i <= 1000000; i++) {
digitalWrite(STEP_PIN, HIGH);
delayMicroseconds(microrotatePerPartmms / speed);
digitalWrite(STEP_PIN, LOW);
delayMicroseconds(microrotatePerPartmms / speed);
button_Left = digitalRead(LEFT_PIN);
button_Right = digitalRead(RIGHT_PIN);
if (button_Left == 0){
digitalWrite(DIR_PIN,LOW);
// break;
} if (button_Right == 0) {
digitalWrite(DIR_PIN, HIGH);
// break;
}
if (Serial.available()){
data = Serial.readString();
d1 = data.charAt(0);
if(d1 == 's'){
break;
}
}
}
}
The code starts with a function declaration named play(). This means that when I will call play() in my program, the code inside this function will be executed.
In this way I made Autohome function too.
And after I went to position making. As I had 5 positions starting from 0 - 0, 1, 2, 3 and 4 I made a formula stepsPerRevolution * pos / 4. For example Steps Per Revolution is 32260 - how much microrotations it does * position that C## gave (0, 1, 2, 3 or 4) / 4
void position(int pos) {
autoHome();
digitalWrite(DIR_PIN,LOW);
int stepForPos = stepsPerRevolution * pos / 4;
for (int i = 1; i <= stepForPos; i++) {
digitalWrite(STEP_PIN, HIGH);
delayMicroseconds(microrotatePerPartmms / speed);
digitalWrite(STEP_PIN, LOW);
delayMicroseconds(microrotatePerPartmms / speed);
if (Serial.available()){
data = Serial.readString();
d1 = data.charAt(0);
if(d1 == 's'){
break;
}
}
}
}
else if (d1 == 'b') { // position
String posStr = data.substring(1);
int pos = posStr.toInt();
position(pos);
}
And for speed:
else if (d1 == 't') { // speed
String posStr = data.substring(1); // taken value of the string starting from the 2nd element
int receivedSpeed = posStr.toInt(); // received speed from C#, converting to an integer
if (receivedSpeed == 0) {
speed = 5;
} else if (receivedSpeed == 1) {
speed = 10;
} else if (receivedSpeed == 2) {
speed = 50;
}
I saw that the speed is not much, and I changed it, by making fast.
if (receivedSpeed == 0) {
speed = 10;
} else if (receivedSpeed == 1) {
speed = 50;
} else if (receivedSpeed == 2) {
speed = 120;
}
Final result¶
And here is how it worked. I used all functions in video below.