im working on an RC car project and im using 2 DC motors as a rear wheels ,one servo motor on front for steering with a nano arduino as a microcontroller, HC 06-slave bluetooth receiver, and L298N module for Fwd/Rev and PWM. for my transmitter im using nano arduino a joystick and HC-06 master.
i need my joystick Y axis to drive fwd/rev and X axis for steering. i manged to test the servo alone for X axis steering and it worked, also when tested the code for FWD/REV on Y axis it worked.. however when i combine my code it doesn't work my servo starts shaking and my DC motors start responding to x and y!!
can someone help me pls.
here are the codes im using:
Master code (transmitter);
// == MASTER DEVICE - Joystick ==
//int xAxis, yAxis;
void setup() {
Serial.begin(9600); // Default communication rate of the Bluetooth
module
}
void loop() {
xAxis = analogRead(A0); // Read Joysticks X-axis
yAxis = analogRead(A1); // Read Joysticks Y-axis
// Send the values via the serial port to the slave HC-05 Bluetooth
device
Serial.write(xAxis/4); // Dividing by 4 for converting from 0 -
1023 to 0 - 256, (1 byte) range
Serial.write(yAxis/4);
delay(20);
}
slave code (servo only);
#include <Servo.h>
Servo myServo;
int yAxis;
void setup() {
myServo.attach(3);
Serial.begin(9600); // Default communication rate of the Bluetooth
module
}
void loop() {
yAxis = 510 / 4;
// Read the incoming data from the Joystick, or the master
Bluetooth device
if(Serial.available() > 0){ // Checks whether data is comming from
the serial port
yAxis = Serial.read(); // Reads the data from the serial port
}
delay(10);
myServo.write(yAxis);
delay(10);
}
slave code for DC motors FWD/REV;
#include <Servo.h>
#define enA 9
#define in1 4
#define in2 5
#define enB 10
#define in3 6
#define in4 7
//int servoPin = 3;
int xAxis;
unsigned int x = 0;
unsigned int y = 0;
int motorSpeedA = 0;
int motorSpeedB = 0;
//Servo Servo1;
void setup() {
pinMode(enA, OUTPUT);
pinMode(enB, OUTPUT);
pinMode(in1, OUTPUT);
pinMode(in2, OUTPUT);
pinMode(in3, OUTPUT);
pinMode(in4, OUTPUT);
Serial.begin(9600); // Default communication rate of the Bluetooth module
// Servo1.attach(servoPin);
}
void loop() {
// Default value - no movement when the Joystick stays in the center
x = 510 / 4;
y = 510 / 4;
// Read the incoming data from the Joystick, or the master Bluetooth device
while (Serial.available() >= 2) {
x = Serial.read();
// delay(10);
// y = Serial.read();
}
delay(10);
// Convert back the 0 - 255 range to 0 - 1023, suitable for motor control code below
xAxis = x*4;
// yAxis = y*4;
// Y-axis used for forward and backward control
if (xAxis < 470) {
// Set Motor A backward
digitalWrite(in1, HIGH);
digitalWrite(in2, LOW);
// Set Motor B backward
digitalWrite(in3, HIGH);
digitalWrite(in4, LOW);
// Convert the declining Y-axis readings for going backward from 470 to 0 into 0 to 255 value for the PWM signal for increasing the motor speed
motorSpeedA = map(xAxis, 470, 0, 0, 255);
motorSpeedB = map(xAxis, 470, 0, 0, 255);
}
else if (xAxis > 550) {
// Set Motor A forward
digitalWrite(in1, LOW);
digitalWrite(in2, HIGH);
// Set Motor B forward
digitalWrite(in3, LOW);
digitalWrite(in4, HIGH);
// Convert the increasing Y-axis readings for going forward from 550 to 1023 into 0 to 255 value for the PWM signal for increasing the motor speed
motorSpeedA = map(xAxis, 550, 1023, 0, 255);
motorSpeedB = map(xAxis, 550, 1023, 0, 255);
}
// If joystick stays in middle the motors are not moving
else {
motorSpeedA = 0;
motorSpeedB = 0;
}
if (motorSpeedA < 70) {
motorSpeedA = 0;
}
if (motorSpeedB < 70) {
motorSpeedB = 0;
}
analogWrite(enA, motorSpeedA); // Send PWM signal to motor A
analogWrite(enB, motorSpeedB); // Send PWM signal to motor B
}
i want to combine them so one of the axis is for DC motors FWD/REV and the other axis is for servo motor right/left.
You must be more explicit with the data you send.
Don't send x=20,y=30 as char[2]={20,30}.
A minimum would be char[4]={'x',20,'y',30}.
Then you will check that you receive complete datagram of 4 char, and then you can check that you don't confuse x with y.
Related
I am now on my project that I need to sort the objects with different colors. I'll put all the objects on a conveyor and the sensor will read the color and the conveyor will transfer the object to the location that the box is place next the conveyor and there is servo motor I have installed to flick the object into the box. I found out that the code can not detect the color of the object(I already check that the sensor work properly).
#include <Servo.h> // include the Servo library
// Define the pins for the TCS230 color sensors
#define TCS230_S0 4
#define TCS230_S1 5
#define TCS230_S2 6
#define TCS230_S3 7
// Define the pins for the servo motors
#define SERVO1 9
#define SERVO2 10
#define SERVO3 11
// Define the RGB color values for each color to be sorted
#define RED_R 200
#define RED_G 0
#define RED_B 0
#define GREEN_R 0
#define GREEN_G 200
#define GREEN_B 0
#define BLUE_R 0
#define BLUE_G 0
#define BLUE_B 200
#define YELLOW_R 200
#define YELLOW_G 200
#define YELLOW_B 0
Servo servo1; // create Servo object for servo1
Servo servo2; // create Servo object for servo2
Servo servo3; // create Servo object for servo3
void setup() {
// initialize the TCS230 color sensor pins
pinMode(TCS230_S0, OUTPUT);
pinMode(TCS230_S1, OUTPUT);
pinMode(TCS230_S2, OUTPUT);
pinMode(TCS230_S3, OUTPUT);
// initialize the servo motor pins
servo1.attach(9);
servo2.attach(10);
servo3.attach(11);
}
void loop() {
int red, green, blue; // variables to store the color values
// read the color values from the TCS230 color sensor
digitalWrite(TCS230_S2, LOW);
digitalWrite(TCS230_S3, HIGH);
red = pulseIn(TCS230_S0, LOW);
green = pulseIn(TCS230_S1, LOW);
digitalWrite(TCS230_S2, HIGH);
digitalWrite(TCS230_S3, HIGH);
blue = pulseIn(TCS230_S0, LOW);
// compare the color values to the predefined RGB values for each color
if (red > RED_R && green < RED_G && blue < RED_B) {
// move servo1 to sort the red object into the corresponding box
servo1.write(45);
delay(1000);
servo1.write(90);
delay(1000);
}
else if (red < GREEN_R && green > GREEN_G && blue < GREEN_B) {
// move servo2 to sort the green object into the corresponding box
servo2.write(45);
delay(1000);
servo2.write(90);
delay(1000);
}
else if (red < BLUE_R && green < BLUE_G && blue > BLUE_B) {
// move servo3 to sort the blue object into the corresponding box
servo3.write(45);
delay(1000);
servo3.write(90);
delay(1000);
}}```
I assume that you're pin variable names match the sensors pin names.
Then your code is utter nonsense. It clearly shows that you have not spent a minute reading any documentation on that sensor.
First of all you never set TCS230_S0, or TCS230_S1 high. So the sensor is turned off. You need to set at least one of those pins high in order to configure the output frequency.
Then you turn S2 low (S1 is still low) and S3 high. This configures the sensor so it outputs the blue value. You then attempt to read red and green pulse width from two output pins.
Then you turn the sensor to output green only and attempt to read blue, again by reading the pulsewidth from an output pin.
First of all you need to turn the sensor to the desired output frequency. Then you need to select a colour you want to measure and then you measure the pulse width of the sensors out pin. S0-S3 are for configuration only.
I want to send multibyte integers,(eg. 1000,10000, etc) from raspberry pi to arduino. It can either be in the form of int or string(will convert it into integer on arduino's side) through i2c. Now, I am able to send data but only till 255, If I try to send 1000, the output on ARduino serial terminal will be 232 and not 1000. I tried to search over the internet for like 4-5 hours, but no luck. Can someone please guide me?
import smbus
import time
bus = smbus.SMBus(1)
address = 0x04
a=1000
#a=str(a)
def writeString(a,b,c,d):
bus.write_i2c_block_data(address, a, [b, c, d])
return -1
while True:
try:
writeString(1000,a,5,0)
time.sleep(1) #delay one second
except KeyboardInterrupt:
quit()
Arduino:
#include <Wire.h>
int data [4];
int x = 0;
void setup() {
Serial.begin(9600);
Wire.begin(0x04);
Wire.onReceive(receiveData); //callback for i2c. Jump to void recieveData() function when pi sends data
}
void loop () {
delay(100); //Delay 0.1 seconds. Something for the arduino to do when it is not inside the reciveData() function. This also might be to prevent data collisions.
}
void receiveData(int byteCount) {
while(Wire.available()) { //Wire.available() returns the number of bytes available for retrieval with Wire.read(). Or it returns TRUE for values >0.
data[x]=Wire.read();
x++;
}
Serial.println("----");
Serial.print(data[0]);
Serial.print("\t");
Serial.print(data[1]);
Serial.print("\t");
Serial.print(data[2]);
Serial.print("\t");
Serial.println(data[3]);
// Serial.print("----");
}
I2C sends and receives BYTES. 1000 in hex is 0x3E8. 232 in hex is 0xE8. Only the low byte is sent.
I'm using an app to either turn on an LED or change the angle of a micro servo depending on which button is pressed (using Arduino). My code works for the LED (while the button is pressed, the LED is on) but nothing happens when I press the button meant to change the angle of the servo to 40.
// Bluetooth serial:
#include <SoftwareSerial.h> // import the serial library
// setup the bluetooth coms
SoftwareSerial BTSerial(8,7);
#include <Servo.h>
int servoPin = 0;
Servo servo;
int angle = 0; // servo position in degrees
int input = 0;
int led2 = 13;
void setup() {
// put your setup code here, to run once:
servo.attach(servoPin);
Serial.begin(9600); // coms w/ computer
BTSerial.begin(9600); // coms w/ Bluetooth
pinMode(led2, OUTPUT);
}
void loop() {
// put your main code here, to run repeatedly:
if (BTSerial.available())
{
input = BTSerial.read();
digitalWrite(led2, LOW);
switch(input) {
case 'E':
angle = 40;
break;
case 'C':
digitalWrite(led2, HIGH);
break;
}
servo.write(angle);
}
}
The input is right as I checked by also turning the LED on in case 'E' where it worked as normal. I had also tried using servo.write() within the case function as well but this didn't work either.
case 'E':
servo.write(40);
break;
You cannot use digital pins 0 or 1 as input:
As mentioned, those are serial send and receive pins. If you power your computer through USB, it can interfere if you try to use them, since it's reading from both the USB to Serial and the pin. Also you have an issue with anything connected (well, not anything, but remove it just to be safe) when you're trying to program. If you use the pins as intended, and program then run it off battery, it should be no problem at all.
Most of us stay away from it because it's a bit of a hassle
Depending on your Arduino model, servo.attach only supports pins 9 and 10:
Note that in Arduino 0016 and earlier, the Servo library supports only servos on only two pins: 9 and 10.
Or you could just use one of those anyway.
I am having trouble with the arduino sound sensor and LEDs. I keep on getting the value of 0 in my serial monitor, the same thing happens with another sound sensor that I have. I am currently trying to make it light up the LEDs based on the sound but with the serial monitor reading 0 it will not activate the code. There should be a picture attached. The lights on the sound sensor is lighting up so I know the GND and 5V is working. Since it is hard to tell I am using 330 ohm resisters. I got the sound sensor from an elegoo starter kit, so I know it might be cheap. The picture is in the link at the end. Thank you.
int MicPin = A0;
int MicValue1 = 0;
int MicValue2 = 0;
int led1 = 2;
int led2 = 4;
int led3 = 6;
int led4 = 8;
void setup() {
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(led3, OUTPUT);
pinMode(led4, OUTPUT);
pinMode(MicPin, OUTPUT);
Serial.begin(9600);
}
void loop() {
MicValue1 = analogRead(MicPin);
Serial.println(MicValue1);
delay(1);
MicValue2 = analogRead(MicPin);
Serial.println(MicValue2);
if (MicValue1 - MicValue2 > 1) {
digitalWrite(led1, HIGH);
delay(2000);
}
else {
digitalWrite(led1, LOW);
}
}
enter image description here
I assume that you have a simple analog-output sensor module that provides 10bit analog values based on the environment volume level. If this assumption is correct, you wired all pins correctly and the received value is always out of range or at the maximum, you maybe had to integrate a resistor to get a valid value. Try a small resistor and increase the resistance until you receive suitable values. Maybe the documentation of your module provides further information.
There is a small rotating knob connected to the sensor on which we need to rotate to adjust particular resistance values, you can see different values in serial monitor out.
Useful link
I am using a analog-output sound sensor module where the output of the sensor module is connected to the arduino and can see arduino is doing Ato D conversion and displaying integers from range 0 to 1023.
But I need to calculate the frequency of the sound getting measure from the sensor.
so could you help me, hwo to calculate the frequecy from this Ato D converted values from arduino.
You don't really need to to ADC conversions do you? All you need to do is detect a rising edge on the input and then count those. Since your sensor will output low-high-low sequences, and since the Arduino will register HIGH as over a certain voltage, that should be adequate.
This code will measure up to around 200 kHz, from an input connected to digital pin 8 on the board:
// Input: Pin D8
volatile boolean first;
volatile boolean triggered;
volatile unsigned long overflowCount;
volatile unsigned long startTime;
volatile unsigned long finishTime;
// timer overflows (every 65536 counts)
ISR (TIMER1_OVF_vect)
{
overflowCount++;
} // end of TIMER1_OVF_vect
ISR (TIMER1_CAPT_vect)
{
// grab counter value before it changes any more
unsigned int timer1CounterValue;
timer1CounterValue = ICR1; // see datasheet, page 117 (accessing 16-bit registers)
unsigned long overflowCopy = overflowCount;
// if just missed an overflow
if ((TIFR1 & bit (TOV1)) && timer1CounterValue < 0x7FFF)
overflowCopy++;
// wait until we noticed last one
if (triggered)
return;
if (first)
{
startTime = (overflowCopy << 16) + timer1CounterValue;
first = false;
return;
}
finishTime = (overflowCopy << 16) + timer1CounterValue;
triggered = true;
TIMSK1 = 0; // no more interrupts for now
} // end of TIMER1_CAPT_vect
void prepareForInterrupts ()
{
noInterrupts (); // protected code
first = true;
triggered = false; // re-arm for next time
// reset Timer 1
TCCR1A = 0;
TCCR1B = 0;
TIFR1 = bit (ICF1) | bit (TOV1); // clear flags so we don't get a bogus interrupt
TCNT1 = 0; // Counter to zero
overflowCount = 0; // Therefore no overflows yet
// Timer 1 - counts clock pulses
TIMSK1 = bit (TOIE1) | bit (ICIE1); // interrupt on Timer 1 overflow and input capture
// start Timer 1, no prescaler
TCCR1B = bit (CS10) | bit (ICES1); // plus Input Capture Edge Select (rising on D8)
interrupts ();
} // end of prepareForInterrupts
void setup ()
{
Serial.begin(115200);
Serial.println("Frequency Counter");
// set up for interrupts
prepareForInterrupts ();
} // end of setup
void loop ()
{
// wait till we have a reading
if (!triggered)
return;
// period is elapsed time
unsigned long elapsedTime = finishTime - startTime;
// frequency is inverse of period, adjusted for clock period
float freq = F_CPU / float (elapsedTime); // each tick is 62.5 ns at 16 MHz
Serial.print ("Took: ");
Serial.print (elapsedTime);
Serial.print (" counts. ");
Serial.print ("Frequency: ");
Serial.print (freq);
Serial.println (" Hz. ");
// so we can read it
delay (500);
prepareForInterrupts ();
} // end of loop
More discussion and information at Timers and counters.
As I suggested you in the other thread, the best is to
filter
amplify
apply a threshold
measure the time between edges
Steps 1, 2, 3 can be performed in software but it is MUCH better to perform them in hardware. The fourth step is what Nick Gammon solution is about... But you have to first make steps 1,2,3 in HW otherwise you will receive a lot of "noisy" readings