I tried to have a random fading pattern on several leds and it leads to flickering because it cannot recognise which led are already on use.
I am in the process of creating a simple lamp that show some light patterns using 6 led and an arduino uno. The goal is that depending on some inputs and a bit of randomisation, the patterns will change. For instance, only 2 lights at the same time but fading up and down randomly on all 6 led. Or 4 lights fading up and down randomly on the 6 leds.
I decided to create a struct that would be a light pattern named a particle, and this particle have a variable named led_position that shows which led it is on at a certain moment. The particle can change its position to light up an other led.
I have tried to add a data field for busy, as you can see and to update the list of available led ( the one without a busy process on it) to no avail.
'''Main code '''' -edited after bartek's comment.
#include "MyTypes.h"
int led0 = 3; // the PWM pin the LED is attached to
int led1 = 5;
int led2 = 6;
int led3 = 9;
int led4 = 10;
int led5 = 11;
//int led;
int brightness;
int fadeAmount;
// Definition of the different particles
particle_type particle[]={
{ 0,led0,0, 2, false },
{ 1,led1,50, 2, false },
{ 2,led2,100, 2, false },
{ 3,led3,80, 2, false },
{ 4,led4,30, 2, false},
{ 5,led5,70, 2, false},
};
led_type led[]={
{ 3,false },
{ 5,false },
{ 6,false },
{ 9,false },
{ 10,false },
{ 11,false },
};
//initiation of the particles
void initiate_particle(particle_type& particle_example,led_type led[]){
//take a random led from list of led
int number=random(6);
Serial.println(number);
led[number];
if (led[number].busy == false){ //if led non-occupied
for (int i=0;i<6;i++){
if (led[i].led_position==particle_example.led_position){
led[i].busy=false;
Serial.println("success");
Serial.println(led[i].led_position);
}
}
particle_example.led_position=led[number].led_position;
Serial.println(particle_example.led_position);
led[number].busy = true ;//take this led as output
}
else{
// initiate_particle( particle_example,led);
}
particle_example.reset = false; //reset turned off
delay(30);
}
void update_light(particle_type& particle_example,led_type led[]){ //updating led brightness
analogWrite(particle_example.led_position, particle_example.brightness); //updating led brightness
if (particle_example.brightness >= 160) {
particle_example.fadeAmount = -particle_example.fadeAmount;
}
if (particle_example.brightness <= 160 && particle_example.brightness >= 100 ) {
particle_example.brightness = particle_example.brightness + 2*particle_example.fadeAmount;
}
if (particle_example.brightness >= 50 && particle_example.brightness <= 100){
particle_example.brightness = particle_example.brightness + particle_example.fadeAmount;
}
if (particle_example.brightness >= 0 && particle_example.brightness <= 50){
particle_example.brightness = particle_example.brightness + 0.5*particle_example.fadeAmount;
}
if (particle_example.brightness <= 0){
particle_example.reset= true;
particle_example.brightness =0;
int number = particle_example.led_position;
particle_example.fadeAmount = -particle_example.fadeAmount;
}
}
void activate_particle(particle_type& particle_example,led_type led[]){ //function to keep led activated
if (particle_example.reset==true){ //if led not initiated or has finished its dimming down
initiate_particle(particle_example, led); //initiate it again
;}
else {
update_light(particle_example,led); //update its brightness
}
}
void setup() { //create led outputs
pinMode(led0, OUTPUT);
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(led3, OUTPUT);
pinMode(led4, OUTPUT);
pinMode(led5, OUTPUT);
Serial.begin(9600); //serial for debug
}
void loop() {
activate_particle(particle[0],led);
activate_particle(particle[1],led);
activate_particle(particle[2],led);
// activate_particle(particle[3],led);
// activate_particle(particle[4],led);
// activate_particle(particle[5],led);
//
delay(10); // 20-17-15-12-10-7-2
}
'''Mytypes.h''''
typedef struct {
int id;
int led_position;
int brightness;
int fadeAmount;
bool reset;
} particle_type;
typedef struct {
int led_position;
bool busy;
} led_type;
The code runs and the particles go from led to led but they sometime merge into a single one and this makes the LED flickers.
The problems are almost non-existent when 1 to 3 particles are activated but become a problem starting at 4 up to 6.
How can I make sure that they don't 'take' the same led to output.
On top of that it seems that some leds are "discarded". How can I make sure that they stay active.
I have created a Bluetooth based smartphone controlled robot (a 4 wheel car) earlier using Arduino and an obstacle avoidance robot.
Now, I wanted to combine both of them. So, I combined their functions and codes in such a manner that felt right to me. But, it kinda seems wrong to my robot.
My Bluetooth Controlled robot was running smoothly. My obstacle avoiding robot was running flawless. But, when I tried to join them, both of them started crying.
I tried to change orders of the functions, adding some functions twice or thrice removing them from some places that didn't feel right then. Nothing was worthy.
I need to upload whole code because I'm not sure where am I doing it wrong
#include <SoftwareSerial.h>
#include <RemoteXY.h>
// RemoteXY connection settings
#define REMOTEXY_SERIAL_RX A2
#define REMOTEXY_SERIAL_TX A3
#define REMOTEXY_SERIAL_SPEED 9600
// RemoteXY configurate
#pragma pack(push, 1)
uint8_t RemoteXY_CONF[] =
{ 255,8,0,54,0,176,0,8,228,4,
5,48,44,26,30,30,0,31,8,1,
6,0,-84,-142,20,20,0,2,26,129,
0,6,37,23,8,0,64,78,97,118,
101,100,0,131,3,51,1,20,5,1,
2,31,82,111,98,111,116,32,67,97,
114,0,131,0,62,5,19,5,2,2,
31,67,111,110,116,114,111,108,108,101,
114,0,129,0,10,45,13,7,0,16,
84,72,69,0,129,0,5,52,25,8,
0,136,83,104,101,105,107,104,0,1,
0,-34,-111,12,12,1,2,31,88,0,
1,4,79,44,12,12,0,37,151,240,
159,147,162,0,65,4,87,9,7,7,
0,65,1,87,17,7,7,0,65,2,
87,25,7,7,0,67,5,3,3,25,
14,0,94,24,51,2,0,86,1,11,
5,0,135,26,31,31,79,78,0,79,
70,70,0 };
// this structure defines all the variables of your control interface
struct {
// input variable
int8_t joystick_1_x; // =-100..100 x-coordinate joystick position
int8_t joystick_1_y; // =-100..100 y-coordinate joystick position
uint8_t rgb_1_r; // =0..255 Red color value
uint8_t rgb_1_g; // =0..255 Green color value
uint8_t rgb_1_b; // =0..255 Blue color value
uint8_t button_1; // =1 if button pressed, else =0
uint8_t button_2; // =1 if button pressed, else =0
uint8_t switch_1; // =1 if switch ON and =0 if OFF
// output variable
uint8_t red_led_r; // =0..255 LED Red brightness
uint8_t blue_led_b; // =0..255 LED Blue brightness
uint8_t green_led_g; // =0..255 LED Green brightness
char text_indicator[51]; // string UTF8 end zero
// other variable
uint8_t connect_flag; // =1 if wire connected, else =0
} RemoteXY;
#pragma pack(pop)
/////////////////////////////////////////////
// END RemoteXY include //
/////////////////////////////////////////////
#define PIN_BUTTON_2 A4
#define PIN_SWITCH_1 A5
#include<AFMotor.h>
#include <NewPing.h>
#include <Servo.h>
#define TRIG_PIN A0
#define ECHO_PIN A1
#define MAX_DISTANCE 250
//#define MAX_SPEED 150 // sets speed of DC motors
//#define MAX_SPEED_OFFSET 20
NewPing sonar(TRIG_PIN, ECHO_PIN, MAX_DISTANCE);
AF_DCMotor left_motor_A(1, MOTOR12_64KHZ);
AF_DCMotor left_motor_B(2, MOTOR12_64KHZ);
AF_DCMotor right_motor_A(3, MOTOR34_64KHZ);
AF_DCMotor right_motor_B(4, MOTOR34_64KHZ);
Servo myservo;
int distance = 100;
int right_motor_speed = 0;
int left_motor_speed = 0;
//define two arrays with a list of pins for each motor
AF_DCMotor RightMotor[2] = {right_motor_A, right_motor_B};
AF_DCMotor LeftMotor[2] = {left_motor_A, left_motor_B};
//speed control of motors
void Wheel (AF_DCMotor * motor, int v) // v = motor speed, motor = pointer to an array of pins
{
if (v > 100) v=100;
if (v < -100) v=-100;
if (v > 0){
motor[0].run(FORWARD);
motor[1].run(FORWARD);
motor[0].setSpeed(v * 1.75);
motor[1].setSpeed(v * 1.75);
}
else if ( v<0 ){
motor[0].run(BACKWARD);
motor[1].run(BACKWARD);
motor[0].setSpeed(v * 1.75);
motor[1].setSpeed(v * 1.75);
/* //digitalWrite (motor [1], FORWARD);
analogWrite (motor [2], (v) * 0.75);
//analogWrite (motor [2], (-v) * 0.75); */
}
else{
motor[0].run(RELEASE);
motor[1].run(RELEASE);
motor[0].setSpeed(0);
motor[1].setSpeed(0);
}
}
int lookRight()
{
RemoteXY.blue_led_b = 255;
RemoteXY.red_led_r = 0;
RemoteXY.green_led_g = 0;
sprintf(RemoteXY.text_indicator, "CHECKING THE RIGHT SIDE.");
myservo.write(50);
delay(500);
int distance = readPing();
delay(100);
myservo.write(115);
return distance;
}
int lookLeft()
{
RemoteXY.blue_led_b = 255;
RemoteXY.red_led_r = 0;
RemoteXY.green_led_g = 0;
sprintf(RemoteXY.text_indicator, "CHECKING THE LEFT SIDE.");
myservo.write(170);
delay(500);
int distance = readPing();
delay(100);
myservo.write(115);
return distance;
delay(100);
}
int readPing()
{
delay(100);
int cm = sonar.ping_cm();
if(cm==0)
{
cm = MAX_DISTANCE ;
}
return cm;
}
void moveStop()
{
left_motor_A.run(RELEASE);
left_motor_B.run(RELEASE);
right_motor_A.run(RELEASE);
right_motor_B.run(RELEASE);
}
void setup()
{
RemoteXY_Init ();
pinMode (PIN_BUTTON_2, OUTPUT);
pinMode (PIN_SWITCH_1, OUTPUT);
myservo.attach(10);
myservo.write(115);
delay(2000);
distance = readPing();
delay(100);
distance = readPing();
delay(100);
distance = readPing();
delay(100);
distance = readPing();
delay(100);
}
void loop()
{
RemoteXY_Handler ();
digitalWrite(PIN_BUTTON_2, (RemoteXY.button_2==0)?LOW:HIGH);
digitalWrite(PIN_SWITCH_1, (RemoteXY.switch_1==0)?LOW:HIGH);
int distanceR = 0;
int distanceL = 0;
delay(40);
if(distance<=27)
{
moveStop();
RemoteXY.blue_led_b = 0;
RemoteXY.red_led_r = 255;
RemoteXY.green_led_g = 0;
sprintf(RemoteXY.text_indicator, "AN OBSTACLE HAS COME IN FRONT OF YOUR ROBOT!!!");
digitalWrite(PIN_BUTTON_2, HIGH);
delay(1500);
distanceR = lookRight();
delay(250);
distanceL = lookLeft();
delay(250);
if(distanceR>=distanceL)
{
RemoteXY.blue_led_b = 255;
RemoteXY.red_led_r = 0;
RemoteXY.green_led_g = 0;
sprintf(RemoteXY.text_indicator, "IT IS GOOD TO GO ON THE RIGHT SIDE.");
}
else
{
sprintf(RemoteXY.text_indicator, "IT IS GOOD TO GO ON THE LEFT SIDE.");
}
}
else
{
RemoteXY.blue_led_b = 0;
RemoteXY.red_led_r = 0;
RemoteXY.green_led_g = 255;
//manage the right motor
Wheel (LeftMotor, RemoteXY.joystick_1_y - RemoteXY.joystick_1_x);
Wheel (RightMotor, RemoteXY.joystick_1_y + RemoteXY.joystick_1_x);
}
distance = readPing();
//manage the right motor
//Wheel (LeftMotor, RemoteXY.joystick_1_y - RemoteXY.joystick_1_x);
//Wheel (RightMotor, RemoteXY.joystick_1_y + RemoteXY.joystick_1_x);
}
I want my Robot to work on my directions and when he senses something on its front end then he should stop there and tell me through a RemoteXY.text_string and then check for obstacles at the left and right side and tell me on which side it is available to go. After that, it should again take my orders via my mobile phone.
Firstly, it became impossible to connect the robot to the Smartphone using Bluetooth because the robot was very busy in doing some other stuffs (only he knows what was he doing). Then, I applied a "RemoteXY Button" on my code (that is not in the code that I'm posting here) with an "if" block; such that if this switch is pressed via the Smartphone, only then the robot will start moving. So, doing this thing helped me to connect my robot to my smartphone via Bluetooth but, when I was connection then the Servo Motor was regularly spinning (again, I don't know why) after secure connection, when I turned that switch on, then my robot took only my first order (which is usually moving forward) and it performed on my first order for almost first 3 to 5 seconds and then the Robot got his system hanged and my smartphone was automatically disconnected from the robot.
I am unable to figure out where is the filth in my code or my code is itself fully filthy. This is the matter, where I need you guys' help
Other information that you might need for better Support/help, I am using:
1). RemoteXY app for Android to Robot Communication
2). Arduino UNO as Microcontroller
3). Arduino IDE for Programming Arduino
4). One SG 90 Servo Motor.
5). Four Geared DC- Motors.
6). L293D Motor Driver Shield for driving Dc motors and the Servo
7). HC SR-04 ultrasonic sensor for obstacle sensing
8). A 12V battery
9). HC-05 Module for Bluetooth Communication
10). A buzzer for external indicator/horn. At pin A4
11). A filthy code for Arduino Programming 😜.
Any help with the code will be appreciated.
Thank You So Much in advance. ❤️
For an arduino robot that needs to perform a lot of function simultaneously you may want to look into this https://forum.arduino.cc/index.php?topic=223286.0
I'm using an external application to sync my RGB peripherals with my WS2812B Strip. I wanted to make a default color that it could switch to when the application isn't running but after 2 seconds of enabling the strip in the software, it goes back to the default color I set (255,255,255).
#include <Adafruit_NeoPixel.h>
#define PIN 6
#define NUMPIXELS 30
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB +
NEO_KHZ800);
void setup() {
pixels.begin();
Serial.begin(19200, SERIAL_8E1);
}
void loop() {
for (int w = 0; w < NUMPIXELS; w++) {
pixels.setPixelColor(w, 255, 255, 255);
}
pixels.show();
int w = 0;
if (Serial.available()) {
int n = 0;
for (int n = 0; n < 3; n++) {
byte rgb[3];
Serial.readBytes(rgb, 3);
uint32_t r = int(rgb[0]);
uint32_t g = int(rgb[1]);
uint32_t b = int(rgb[2]);
for (int i = 0; i < NUMPIXELS; i++) {
pixels.setPixelColor(i, r, g, b);
}
pixels.show();
}
}
}
The function Serial.available() does something else than what you expect:
You expect it to return if there is a communication partner available. Instead it checks if there are bytes to read available:
Get the number of bytes (characters) available for reading from the serial port. (Source: https://www.arduino.cc/en/Serial/Available )
This means: Your Arduino has run out of bytes to read, because it empties the pipeline too fast. So, as there are no more bytes to read, it will just make the leds show white.
Sidenote: The if condition should be changed to reflect this (see post on Arduino website):
if (Serial.available() > 0) {
I am using Processing (java) to communicate over serial to an Arduino which controls two servos and a laser. Everything works independently, however when I turn the laser on using Processing I am unable to control the servos until I turn the laser back off.
Troubleshooting I've tried:
Manually sending commands to the Arduino using Arduino Serial or
Putty results in thethe Arduino working as expected (servo control is
independent of laser status)
Putting the Arduino in the serial-bridge configuration to monitor what
serial commands Processing is sending to the Arduino, and it is as
expected (motor positions, laser status)
I am using an external power supply so I know its not a
max-current-draw issue. (and it works
Included delays in Processing, flushing the Arduino buffer.
Used all "\n", "\r", "\r\n" combinations.
Here is my processing program :
import processing.serial.*;
import org.gamecontrolplus.gui.*;
import org.gamecontrolplus.*;
import net.java.games.input.*;
String ard_ser = "/dev/ttyACM0";
ControlIO control;
ControlDevice stick;
float px, py;
int deg_x, deg_y;
boolean trailOn;
Serial myPort;
ArrayList<PVector> shadows = new ArrayList<PVector>();
ArrayList<PVector> trail = new ArrayList<PVector>();
public void setup() {
size(400, 400);
myPort = new Serial(this, Serial.list()[0],9600);
printArray(Serial.list());
// Initialise the ControlIO
control = ControlIO.getInstance(this);
// Find a device that matches the configuration file
stick = control.getMatchedDevice("joystick");
if (stick == null) {
println("No suitable device configured");
System.exit(-1); // End the program NOW!
}
// Setup a function to trap events for this button
stick.getButton("LASER").plug(this, "toggleLaser", ControlIO.ON_PRESS);
}
// Poll for user input called from the draw() method.
public void getUserInput() {
px = map(stick.getSlider("X").getValue(), -1, 1, 0, width);
deg_x = int(map(stick.getSlider("X").getValue(),-1,1,0,180));
py = map(stick.getSlider("Y").getValue(), -1, 1, 0, height);
deg_y = int(map(stick.getSlider("Y").getValue(),-1,1,0,180));
//stick.getButton("LASER").plug(this,"toggleLaser",ControlIO.);
}
// Event handler for the Laser button
public void toggleLaser() {
println("laser");
if (myPort.available()>0){
myPort.write("-1\n");
}
//delay(1000);
return;
}
public void draw() {
getUserInput(); // Polling
background(255, 255, 240);
// Draw shadows
fill(0, 0, 255, 32);
noStroke();
for (PVector shadow : shadows)
ellipse(shadow.x, shadow.y, shadow.z, shadow.z);
if ( trail.size() > 1) {
stroke(132, 0, 0);
for (int n = 1; n < trail.size(); n++) {
PVector v0 = trail.get(n-1);
PVector v1 = trail.get(n);
line(v0.x, v0.y, v1.x, v1.y);
v0 = v1;
}
}
// Show position
noStroke();
fill(255, 64, 64, 64);
ellipse(px, py, 20, 20);
String position = str(deg_x)+','+str(deg_y)+'\n';
if (myPort.available()>0){
//println(position);
myPort.write(position);
}
delay(10);
}
It has a little visualization to monitor the motor location, and basically just sends "mot_x_pos,mot_y_pos \n", and a "-1\n" to toggle the laser.
example output serial stream:
90,90\n
50,50\n
-1\n
The Arduino code parses the stream and controls the motors/laser:
#include <Servo.h>
bool laser = true;
// true sets the value high (off for my transistor)
char val = 0;
const int laser_pin = 7;
int out1 = 9; //servo pins
int out2 = 11;
boolean newData= true;
Servo servo_x;
Servo servo_y;
int pos_x =0;
int pos_y =0;
int x_prev = 90;
int y_prev = 90;
void setup() {
Serial.begin(9600);
Serial.println("<Arduino is ready>");
servo_x.attach(out1);
servo_y.attach(out2);
pinMode(laser_pin, OUTPUT);
digitalWrite(laser_pin, laser); //turn laser off on startup
}
void loop(){
while(Serial.available()>0){
pos_x = Serial.parseInt();
pos_y = Serial.parseInt();
val = Serial.read(); // this catches the newline escape characters
if ( (pos_x<0) || (pos_y<0) ){
//toggle laser
if(laser){
laser = false;
}
else {laser = true;}
digitalWrite(laser_pin, laser);
}
else if( (val == '\n') || (val == '\r') ){
if(pos_x != x_prev){ //only write to the motors if something has changed
servo_x.write(pos_x);
x_prev = pos_x;
}
if(pos_y != y_prev){
servo_y.write(pos_y);
y_prev = pos_y;
}
}
}
}
Any suggestions would be appreciated, thanks.
Would help if you provided the sequence of commands that's not working.
Your Arduino code tries to read two int's, but you're only sending one with the laser command. That'll get out of synch (parseInt doesn't care about the ends of lines, it's happy to go to the next line)
Try
Having your laser button send "-1,-1" so all lines have two numbers on them
Better, create a better-structured format for your lines: Start with a letter that says whether it's a servo or laser command, then read what's needed, then make sure you find a '\n', then repeat.