Send a character via Bluetooth

By the way, it's always a good idea to define your Clock Timers in the Blocks:

Timers

1 Like

Hello Chris,

Please check the available Arduino codes for Robot arm
D_Cube_Robot_Arm.txt (2.1 KB)

Please let me know any modification to be done

Hi Dayan

Just had a quick look at your Arduino Sketch. There is a While loop inside the Main loop - that probably accounts for the occasional times things get stuck. I will up date the code and post it here.

1 Like

So, I notice also that a tiny Delay(x) has been used in all procedures. Delay() should be avoided because it blocks everything, which is not good for the hardware. If a time interval is necessary, add it into the Main loop - not forgetting that the App's time interval must be tweaked too.

D_Cube_Robot_Arm2.txt (3.7 KB)


#include <Servo.h>
Servo axis_one;
Servo axis_two;
Servo axis_three;
Servo grip; //0 30

int axis_one_ctr = 90;
int axis_two_ctr = 130; // min70 , max150
int axis_three_ctr = 40;
int x = 20;
int y = 50;
char in;
unsigned int igUpdateTime;

void setup()
{
         Serial.begin(9600);

         axis_one.attach(8);
         axis_two.attach(9);
         axis_three.attach(10);
         grip.attach(13);
         axis_one.write(axis_one_ctr);
         axis_two.write(axis_two_ctr);
         axis_three.write(axis_three_ctr);
         grip.write(0);
}

void loop()
{
         //Excute loop every 40 milliseconds, 10 milliseconds faster than the App sends to avoid buffer over-run

	     if((millis() - igUpdateTime) > 40)
         {
               igUpdateTime = millis();

               if(Serial.available() > 0)
               {
                     in = Serial.read();

                     switch (in)
                     {
                         case 'X':
                                   axis_one_left();
                                   break;

                         case 'x';
                                   axis_one_right();
                                   break;

                         case 'Y';
                                   axis_two_forward();
                                   break;

                         case 'y'
                                   axis_two_backword();
                                   break;

                         case 'Z'
                                   axis_three_forward();
                                   break;

                         case 'z'
                                   axis_three_backword();
                                   break;

                         case 'O'
                                   axis_two_ctr = 1;
                                   axis_two_forward();
                                   break;

                         case 'C'
                                   axis_two_ctr = 0;
                                   axis_two_backword();
                                   break;
                     }
               }
         }
         // Serial.println('S');
}

void axis_one_right()
{
         axis_one_ctr++;
         axis_one.write(axis_one_ctr);
         // Serial.println("Come");

         if (axis_one_ctr > 170)
         {
               axis_one_ctr = 170;
         }
}

void axis_one_left()
{
         axis_one_ctr--;
         axis_one.write(axis_one_ctr);
         //Serial.println("Come");

         if (axis_one_ctr < 10)
         {
               axis_one_ctr = 10;
         }
}

void gripper_open() {

}
void gripper_close() {

}
void axis_two_forward()
{
         axis_two_ctr++;
         axis_two.write(axis_two_ctr);

         if (axis_two_ctr > 150)
         {
               axis_two_ctr = 150;
         }
}

void axis_two_backword()
{
         axis_two_ctr--;
         axis_two.write(axis_two_ctr);
         // Serial.println("Come");

         if (axis_two_ctr < 70)
         {
               axis_two_ctr = 70;
         }
}

void axis_three_forward()
{
         axis_three_ctr++;
         axis_three.write(axis_three_ctr);

         if (axis_three_ctr > 120)
         {
               axis_three_ctr = 120;
         }
}

void axis_three_backword()
{
         axis_three_ctr--;
         axis_three.write(axis_three_ctr);

         if (axis_three_ctr < 5)
         {
               axis_three_ctr = 5;
         }
}

Hi again

Can you record a video when the Arm is working? I think it will encourage others to have a go and not be afraid of the project size.

What is the slider graphic going to do? Will that control the Gripper? If so, you need to seperate the slide from the thumb button and put them into a Canvas component to make them operational (thumb would be a sprite). Alternatively, you could use App Inventor's Slider component.

Edit: Why is the App sending a stream of 'S'?

Yes Now it is working perfectly no any stuck at all

I think you are suggesting record the video and post it on website, Yes we are planing to post some live video that has been done by the students, The thing is all our school are closed due to pandemic,

We are planing to use this app for the control robot . So that we can use speed control of the robot.

" S " is for stop the robot during the button is unpressed , Red arrow buttons for robot control

I noticed that speed of the rotating of servo motors bit slow now

Hello Chris ,
Can you please advise how to fixed the orientation to landscape

Here in the Screen Properties Palette:

You can tweak-down the milliseconds in the Sketch. Currently 40, try 20.

OK, I thought it might be - it needs to be added to the Sketch.

1 Like

Ah yes, that is a good idea.

We are in lock-down here too (Wales, UK). At least there is hope on the horizon, huge production of vaccine now and it is possible the virus will be defeated world-wide by this time next year.

Dear Chris,
as far as I remember the millis() returns an unsigned long.
So probably by doing:
igUpdateTime = millis();
could lead to an unpredictable result when it overcomes the unsigned int.
What are your thought about ?

Merry Xmas to all and happy new year full of vaccine ... :rofl: :rofl: :rofl:
Cheers , Ugo

Hi Ugo

That's a good point and I'm not sure of the answer. On 64bit systems, unsigned int is long (i.e. long is effectively redundant). Certainly other examples using elapsed millis for loop timing use unsigned int (has twice the capacity of int), but whether that is correct for Arduino - you have disturbed a doubt :slightly_smiling_face:

OK, depends on the exact board being used as to what is supported and thus capacity but the clear winner is unsigned long.

Arduino's millis() however has a safety catch - it only accumulates 50 days, then goes back to zero - so it's not starting in 1970 as in some other languages.

........ looking forward to being vaccinated! :owl:

Hi Dayan

Following Ugo's comments and knowing you are using an Uno, I have modified the Sketch to record elapsed milliseconds as an unsigned long value:

D_Cube_Robot_Arm4.txt (3.7 KB) ..was D_Cube_Robot_Arm3.txt


#include <Servo.h>
Servo axis_one;
Servo axis_two;
Servo axis_three;
Servo grip; //0 30

int axis_one_ctr = 90;
int axis_two_ctr = 130; // min70 , max150
int axis_three_ctr = 40;
int x = 20;
int y = 50;
char in;
unsigned long lgUpdateTime; //was unsigned int

void setup()
{
         Serial.begin(9600);

         axis_one.attach(8);
         axis_two.attach(9);
         axis_three.attach(10);
         grip.attach(13);
         axis_one.write(axis_one_ctr);
         axis_two.write(axis_two_ctr);
         axis_three.write(axis_three_ctr);
         grip.write(0);

         lgUpdateTime = millis();
}

void loop()
{
         //Excute loop every 20 milliseconds, faster than the App sends to avoid buffer over-run

	     if((millis() - lgUpdateTime) > 20)
         {
               lgUpdateTime = millis();

               if(Serial.available() > 0)
               {
                             in = Serial.read();
                     switch (in)
                     {
                         case 'X':
                                   axis_one_left();
                                   break;

                         case 'x';
                                   axis_one_right();
                                   break;

                         case 'Y';
                                   axis_two_forward();
                                   break;

                         case 'y'
                                   axis_two_backword();
                                   break;

                         case 'Z'
                                   axis_three_forward();
                                   break;

                         case 'z'
                                   axis_three_backword();
                                   break;

                         case 'O'
                                   axis_two_ctr = 1;
                                   axis_two_forward();
                                   break;

                         case 'C'
                                   axis_two_ctr = 0;
                                   axis_two_backword();
                                   break;

                         case 'S'
                                   //do something;
                                   break;
                     }
               }
         }
         // Serial.println('S');
}

void axis_one_right()
{
         axis_one_ctr++;
         axis_one.write(axis_one_ctr);
         // Serial.println("Come");

         if (axis_one_ctr > 170)
         {
               axis_one_ctr = 170;
         }
}

void axis_one_left()
{
         axis_one_ctr--;
         axis_one.write(axis_one_ctr);
         //Serial.println("Come");

         if (axis_one_ctr < 10)
         {
               axis_one_ctr = 10;
         }
}

void gripper_open() {

}
void gripper_close() {

}

void axis_two_forward()
{
         axis_two_ctr++;
         axis_two.write(axis_two_ctr);

         if (axis_two_ctr > 150)
         {
               axis_two_ctr = 150;
         }
}

void axis_two_backword()
{
         axis_two_ctr--;
         axis_two.write(axis_two_ctr);
         // Serial.println("Come");

         if (axis_two_ctr < 70)
         {
               axis_two_ctr = 70;
         }
}

void axis_three_forward()
{
         axis_three_ctr++;
         axis_three.write(axis_three_ctr);

         if (axis_three_ctr > 120)
         {
               axis_three_ctr = 120;
         }
}

void axis_three_backword()
{
         axis_three_ctr--;
         axis_three.write(axis_three_ctr);

         if (axis_three_ctr < 5)
         {
               axis_three_ctr = 5;
         }
}

Edit: Above code typo corrected.

Hi Chris,
thanks for your answer.
Probably I'm too old: when I started to "code" it was 1982 and an integer was a huge amount (15 bits + sign) of memory. Back to the present: to avoid any doubt normally I use unsigned long and I let the compiler do the job ... :grin:
Best, Ugo.

.... You can never be too old to program Ugo :muscle:

1 Like