I'm trying to read signals from fs-ct6b using Mega 2560 with this code:
int val;
int ch_in[6] = {2, 3, 4, 5, 6, 7};
int ch_out[6] = {8, 9, 10, 11, 12, 13};
void setup() {
for (int i = 0; i < 6; i++){
pinMode(ch_in[i], INPUT);
pinMode(ch_out[i], OUTPUT);
}
Serial.begin(9600);
}
void loop() {
for (int i = 0; i < 6; i++){
val = pulseIn(ch_in[i], HIGH);
Serial.print("Ch #");
Serial.print(i + 1, DEC);
Serial.print(" = ");
Serial.println(val, DEC);
};
Serial.println("\n");
delay(100);
}
but the received values are grater by 300-400 than I expect. For example throttle values changes between 1418 and 2442, but the same RC connected to my quad in Mission Planner\multiwii GUI gives ~1100 - 1950. What is my problem?
This version of pulseIn() works fine:
ulong pulseIn(int pin, int timeout){
ulong uStart, uEnd, _timer, _pass;
_timer = micros();
while (HIGH == digitalRead(pin)){
_pass = micros() - _timer;
if (_pass > TIME_OUT)
return 0;
};
while (LOW == digitalRead(pin)){
_pass = micros() - _timer;
if (_pass > TIME_OUT)
return 0;
};
uStart = micros();
while (HIGH == digitalRead(pin)){
_pass = micros() - _timer;
if (_pass > TIME_OUT)
return 0;
};
uEnd = micros();
return uEnd - uStart;
}
The other way is to use interrupts as shown here:
http://rcarduino.blogspot.ru/2012/01/how-to-read-rc-receiver-with.html
UPD. The problem was in Arduino IDE version installed by package manager. The "original" version from arduino.cc works fine.
Related
I'm making an Arduino reverse stopwatch..but Seems to have a problem with millis() function
Whenever I upload the code on Arduino the millis starts running itself..how can I keep it at 0 until I call the millis. or any alternatives to solve it...
#include "SevSeg.h"
int button1 = 11;
int button2 = 12;
int button3 = 13;
int value = 10;
int timer = 0;
bool n = true;
SevSeg Display;
void setup() {
Serial.begin(9600);
byte numDigits = 2;
byte digitPins[] = {9,8};
byte segmentPins[] = {10,2, 3, 4, 5, 6, 7,1};
bool resistorsOnSegments = true;
bool updateWithDelays = true;
byte hardwareConfig = COMMON_ANODE;
Display.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments);
Display.setBrightness(100);
}
void loop() {
Display.setNumber(value, 1);
Display.refreshDisplay();
if (digitalRead(11)==HIGH){
Start(value);
}
}
void Start(int value){
while(n){
unsigned long timerGlobal = millis();
Display.setNumber(value-timerGlobal/1000, 1);
Display.refreshDisplay();
if ((value-timerGlobal/1000) == 0){
n = false;
}
}
}
In arduino UNO
extern volatile unsigned long timer0_millis;
noInterrupts ();
timer0_millis = 0;
interrupts ();
But it makes no sense at all.
Simply remember the previous millis and calculate time passed (by substracting).
This should work
//#include "SevSeg.h"
int button1 = 11;
int button2 = 12;
int button3 = 13;
int value = 10;
int timer = 0;
bool n = true;
//Added
int currentTime = 0;
long int t0 = 0;
long int t1 = 0;
//SevSeg Display;
void setup() {
Serial.begin(9600);
byte numDigits = 2;
byte digitPins[] = {9,8};
byte segmentPins[] = {10,2, 3, 4, 5, 6, 7,1};
bool resistorsOnSegments = true;
bool updateWithDelays = true;
//byte hardwareConfig = COMMON_ANODE;
//Display.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments);
//Display.setBrightness(100);
}
void loop() {
//Display.setNumber(value, 1);
// Display.refreshDisplay();
if (digitalRead(11)==HIGH){
Start(value);
}
}
void Start(int value){
t0 = millis();
while(n){
t1 = millis();
if(t1 > (1000+t0)){
//has passed 1 second
currentTime++;
if(value-currentTime == 0){
n = false;
}
}
unsigned long timerGlobal = t1-t0;
//Display.setNumber(value-timerGlobal/1000, 1);
//Display.refreshDisplay();
}
}
Just implement a function that subtract the current millis from the previous millis()
The arduino millis() function is not a function that starts a timer. The millis function is meant to get the elapsed milliseconds since the program started.
Keep in mind that the millis() value will overflow afther:
50 days and 70 minutes. so afther this time the millis() will return 0 again and start over again.
You could implement your own timer using interrupts on the arduino. But like a good programmer always say's if something already exits why make it again? just use the millis() and subtract the current from the previous. But keep in mind of the overflow.
I am having a problem with reading random data in my Arduino Mega (Master) from my Arduino Uno (Slave) while using I2C communication.
Some background: I am reading Encoder data from the Uno and sending to the Mega via I2C communication. The encoder data is been used in the MEga to adjust the speed of a motor so that the revolutions per second of the different wheels have the same value.
The issue of reading random data arises when I include an IF condition or function.
Even if the IF condition included is an empty one or a call to function which has an empty body it starts to read random wrong data from the Uno.
If i don't have the adjusting part (IF condition/ function) of the code the reading of the data from the Uno works fine.
If anybody can help, it would be greatly appreciated.
Master Code:
#include <SoftwareSerial.h>
#include <SabertoothSimplified.h>
// Include the required Wire library for I2C<br>#include
#include <Wire.h>
// RX on pin 17 (to S2), TX on pin 16 (to S1).
SoftwareSerial SWSerial(NOT_A_PIN, 16);
// Use SWSerial as the serial port.
SabertoothSimplified ST(SWSerial);
//////////////////ENCODER DATA//////////////////
unsigned int revolutions_L_rpm = 0;
unsigned int revolutions_R_rpm = 0;
int16_t x = 0;
int16_t y = 0;
////////////////////////////////////////////////
//////////////VARIABLES FOR ADJUST//////////////
int error = 0;
int kp = 12;
int adjusted = 0;
////////////////////////////////////////////////
////////////////////MOTORS//////////////////////
//Declare the arduino pins
int LEDg = 7;
int LEDr = 6;
int LEDy = 5;
int speedVar = 0;
int speedOne = 0;
int speedTwo = 0;
int power;
////////////////////END/////////////////////////
void setup() {
//initlize the mode of the pins
pinMode(LEDg,OUTPUT);
pinMode(LEDr,OUTPUT);
pinMode(LEDy,OUTPUT);
//set the serial communication rate
Serial.begin(9600);
SWSerial.begin(9600);
Wire.begin();
}
void loop()
{
//check whether arduino is reciving signal or not
if(Serial.available() > 0){
char val = Serial.read();//reads the signal
Serial.print("Recieved: ");
Serial.println(val);
switch(val){
/*********Increase speed by 1 as long as e(triangle) is held*********/
case 'a':
forward();
break;
/*********Decrease speed by 1 as long as g(x) is held*********/
case 'c':
reverse();
break;
/*********Increase speed by 1 as long as e(triangle) is held*********/
case 'd':
turnLeft();
break;
/*********Decrease speed by 1 as long as g(x) is held*********/
case 'b':
turnRight();
break;
/*********Toggle when Circle is held for 5 seconds*********/
case 'f':
toggleSwitch(LEDy);
break;
/*********Toggle when Square is held for 5 seconds*********/
case 'h':
stopMotors();
break;
}
Serial.print("sppedVar = ");
Serial.print(speedVar);
Serial.print("\tleftSpeed: ");
Serial.print(speedOne);
Serial.print("\trightSpeed: ");
Serial.println(speedTwo);
}
Wire.requestFrom(9,4); // Request 4 bytes from slave arduino (9)
byte a = Wire.read();
Serial.print("a: ");
Serial.print(a);
byte b = Wire.read();
Serial.print(" b: ");
Serial.print(b);
byte e = Wire.read();
Serial.print(" --- e: ");
Serial.print(e);
byte f = Wire.read();
Serial.print(" f: ");
Serial.print(f);
x = a;
x = (x << 8) | b;
Serial.print("\tX: ");
Serial.print(x);
y = e;
y = (y << 8) | f;
Serial.print("\tY: ");
Serial.print(y);
revolutions_L_rpm = x;
revolutions_R_rpm = y;
if ((revolutions_L_rpm != revolutions_R_rpm) && (speedVar != 0)){
error = 0;
error = revolutions_L_rpm - revolutions_R_rpm;
adjusted = error/kp;
Serial.print("Error: ");
Serial.print(error);
Serial.print("Error/kp: ");
Serial.println(adjusted);
if ((speedTwo < 20) && (speedTwo > -20)){
speedTwo -= adjusted;
power = speedTwo;
ST.motor(2, -power);
//delay(20);
}
}
// Print out rpm
Serial.print("Left motor rps*100: ");
Serial.print(revolutions_L_rpm);
Serial.print(" ///// Right motor rps*100: ");
Serial.println(revolutions_R_rpm);
// Print out speed
Serial.print("speedOne: ");
Serial.print(speedOne);
Serial.print("\tspeedTwo: ");
Serial.println(speedTwo);
delay(1000);
}
Slave code:
// Include the required Wire library for I2C<br>#include <Wire.h>
#include <Wire.h>
// Checked for main program
volatile boolean counterReady;
// Internal to counting routine
unsigned int timerPeriod;
unsigned int timerTicks;
unsigned long overflowCount;
// The pin the encoder is connected
int encoder_in_L = 2;
int encoder_in_R = 3;
// The number of pulses per revolution
// depends on your index disc!!
unsigned int pulsesperturn = 16;
// The total number of revolutions
int16_t revolutions_L = 0;
int16_t revolutions_R = 0;
int16_t revolutions_L_rpm = 0;
int16_t revolutions_R_rpm = 0;
// Initialize the counter
int16_t pulses_L = 0;
int16_t pulses_R = 0;
byte myData[4];
// This function is called by the interrupt
void count_L() {
pulses_L++;
}
void count_R() {
pulses_R++;
}
void startCounting(unsigned int ms) {
counterReady = false; // time not up yet
timerPeriod = ms; // how many ms to count to
timerTicks = 0; // reset interrupt counter
overflowCount = 0; // no overflows yet
// Reset timer 2
TCCR2A = 0;
TCCR2B = 0;
// Timer 2 - gives us our 1 ms counting interval
// 16 MHz clock (62.5 ns per tick) - prescaled by 128
// counter increments every 8 µs.
// So we count 125 of them, giving exactly 1000 µs (1 ms)
TCCR2A = bit (WGM21) ; // CTC mode
OCR2A = 124; // count up to 125 (zero relative!!!!)
// Timer 2 - interrupt on match (ie. every 1 ms)
TIMSK2 = bit (OCIE2A); // enable Timer2 Interrupt
TCNT2 = 0; // set counter to zero
// Reset prescalers
GTCCR = bit (PSRASY); // reset prescaler now
// start Timer 2
TCCR2B = bit (CS20) | bit (CS22) ; // prescaler of 128
}
ISR (TIMER2_COMPA_vect){
// see if we have reached timing period
if (++timerTicks < timerPeriod)
return;
TCCR2A = 0; // stop timer 2
TCCR2B = 0;
TIMSK2 = 0; // disable Timer2 Interrupt
counterReady = true;
if(counterReady){
Serial.print("Pulses_L: ");
Serial.print(pulses_L);
Serial.print(" Pulses_R: ");
Serial.println(pulses_R);
// multiplying by 100 to get a greater difference to compare
revolutions_L_rpm = (pulses_L * 100) / pulsesperturn;
revolutions_R_rpm = (pulses_R * 100) / pulsesperturn;
// Total revolutions
// revolutions_L = revolutions_L + (pulses_L / pulsesperturn);
// revolutions_R = revolutions_R + (pulses_R / pulsesperturn);
pulses_L = 0;
pulses_R = 0;
}
}
void requestEvent() {
myData[0] = (revolutions_L_rpm >> 8) & 0xFF;
myData[1] = revolutions_L_rpm & 0xFF;
myData[2] = (revolutions_R_rpm >> 8) & 0xFF;
myData[3] = revolutions_R_rpm & 0xFF;
Wire.write(myData, 4); //Sent 4 bytes to master
}
void setup() {
Serial.begin(9600);
pinMode(encoder_in_L, INPUT);
pinMode(encoder_in_R, INPUT);
attachInterrupt(0, count_L, RISING); //attachInterrupt(digitalPinToInterrupt(encoder_in_L, count_L, RISING);
attachInterrupt(1, count_R, RISING); //attachInterrupt(digitalPinToInterrupt(encoder_in_R, count_R, RISING);
// Start the I2C Bus as Slave on address 9
Wire.begin(9);
// Attach a function to trigger when something is received.
Wire.onRequest(requestEvent);
}
void loop() {
// stop Timer 0 interrupts from throwing the count out
byte oldTCCR0A = TCCR0A;
byte oldTCCR0B = TCCR0B;
TCCR0A = 0; // stop timer 0
TCCR0B = 0;
startCounting (1000); // how many ms to count for
while (!counterReady)
{ } // loop until count over
// Print out rpm
Serial.print("Left motor rps: ");
Serial.println(revolutions_L_rpm);
Serial.print("Right motor rps: ");
Serial.println(revolutions_R_rpm);
// Print out revolutions
// Serial.print("Left motor revolution count: ");
// Serial.println(revolutions_L);
// Serial.print("Right motor revolution count: ");
// Serial.println(revolutions_R);
// restart timer 0
TCCR0A = oldTCCR0A;
TCCR0B = oldTCCR0B;
delay(200);
}
Some students from my school are working on a project to measure vibrations (eg. earthquakes) and print the results from two sensors (Piezo knock and vibration sensor) to lcd shield. They probably compiled some codes from the internet. Their original code was like this:
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
int referansDegeri = 800;
int knockSensor = 0;
int val = 0;
int sensorLevel = map;
int statePin = LOW;
int THRESHOLD = 100;
const int analogPin = A0;
int vib_pin=7;
void setup()
{
int sensorReading = analogRead(analogPin);
// map the result to a range from 0 to the number of LEDs:
int sensorLevel = map(sensorReading, 0, 1023, 0, sensorCount);
pinMode(vib_pin,INPUT);
Serial.begin(9600);
}
void loop()
{
int sensorDegeri = analogRead(A0);
Serial.print(sensorDegeri); //Okuduğumuz değer ekrana yazdırılıyor
if (sensorDegeri >= referansDegeri){
Serial.println("siddetli sarsinti");
}
else{
Serial.println("dusuk sarsinti");
}
delay(1);
}
val = analogRead(knockSensor);
if (val >= THRESHOLD) {
statePin = !statePin;
digitalWrite(ledPin, statePin);
Serial.println("Knock!");
delay(100);
int val;
val=digitalRead(vib_pin);
if(val==1)
{
digitalWrite(led_pin,HIGH);
delay(1000);
digitalWrite(led_pin,LOW);
delay(1000);
}
else
digitalWrite(led_pin,LOW);
}
This code gave this error (exit status):
'sensorCount' was not declared in this scope
Knowing that the students have one knock sensor, I changed the sensorCount to 1 while mapping it so it would seem
int sensorLevel = map(sensorReading, 0, 1023, 0, 1);
then it started giving this error (exit status):
'val' does not name a type
I made some search however, could not find a specific result so cannot fix the problem. But I believe it is important to mention that students were using LED Bar Graph previously, alongside LCD shield, but they have now removed it.
Currently I'm controlling my BLDC motor using a keypad, keying in the servo value (0-180). But my supervisor needs me to control it using a value between 0-9000 and not 0-180. I have been learning about the map() function. Somehow I don't quite understand and I'm currently stuck trying to incorporate it with my code. How do I map servo values of (0-180) to (0-9000)? Here is my code:
#include <Servo.h>
#include <Keypad.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
// Set the LCD I2C address
Servo myservo;
const byte ROWS = 4; //four rows
const byte COLS = 3; //three columns
char keys[ROWS][COLS] = {
{'1', '2', '3'},
{'4', '5', '6'},
{'7', '8', '9'},
{'*', '0', '#'}
};
byte rowPins[ROWS] = {9, 8, 7, 6};
//row pinouts of the keypad (L1, L2, L3, L4)
byte colPins[COLS] = {5, 4, 3};
//column pinouts of the keypad (R1, R2, R3)
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
// STATE CONDITION FOR MAIN LOOP
enum { enter_values, spin , finish } systemstate;
//FOR MOTORSPIN
unsigned long previousMillis = 0;
long interval = 1000;
// RPM MEASUREMENT
const int dataIN = 2; //IR sensor INPUT
unsigned long prevmillis; // To store time
unsigned long duration; // To store time difference
unsigned long lcdrefresh; // To store time for lcd to refresh
int rpm; // RPM value
boolean currentstate; // Current state of IR input scan
boolean prevstate; // State of IR sensor in previous scan
// DECLARE
int stage1speed , stage1time , stage2speed , stage2time , stage3speed , stage3time ;
void setup() {
Serial.begin(9600);
lcd.begin(20, 4);
myservo.attach(11);
systemstate = enter_values; // set up the starting state
pinMode(dataIN, INPUT);
prevmillis = 0;
prevstate = LOW;
lcd.setCursor(4, 1);
lcd.print("SPIN COATER");
lcd.setCursor(6, 2);
lcd.print("MACHINE");
delay(5000);
lcd.clear();
lcd.setCursor(3, 1);
lcd.print("S = speed(sv)");
lcd.setCursor(3, 2);
lcd.print("T = time(sec)");
delay(5000);
lcd.clear();
lcd.setCursor(3, 1);
lcd.print("Range of Speed");
lcd.setCursor(3, 2);
lcd.print("0-180 sv");
delay(5000);
lcd.clear();
}
//FUNCTION FOR KEY IN SPEED AND TIME
void enter_speed_time() {
lcd.setCursor(0, 0);
lcd.print("S=");
lcd.setCursor(0, 1);
lcd.print("T=");
lcd.setCursor(0, 2);
lcd.print("S=");
lcd.setCursor(0, 3);
lcd.print("T=");
lcd.setCursor(10, 0);
lcd.print("S=");
lcd.setCursor(10, 1);
lcd.print("T=");
lcd.setCursor(10, 2);
lcd.print("RPM");
stage1speed = getTheNumber();
lcd.setCursor(2, 0);
lcd.print(stage1speed);
Serial.print(stage1speed);
lcd.print("sv");
stage1time = getTheNumber();
lcd.setCursor(2, 1);
lcd.print(stage1time);
Serial.print(stage1time);
lcd.print("sec");
stage2speed = getTheNumber();
lcd.setCursor(2, 2);
lcd.print(stage2speed);
Serial.print(stage2speed);
lcd.print("sv");
stage2time = getTheNumber();
lcd.setCursor(2, 3);
lcd.print(stage2time);
Serial.print(stage2time);
lcd.print("sec");
stage3speed = getTheNumber();
lcd.setCursor(12, 0);
lcd.print(stage3speed);
Serial.print(stage3speed);
lcd.print("sv");
stage3time = getTheNumber();
lcd.setCursor(12, 1);
lcd.print(stage3time);
Serial.print(stage3time);
lcd.print("sec");
}
// FUNCTION TO GET NUMBERS FROM 4X3 MATRIC KEYPAD
int getTheNumber() {
char buffer[4];
int i = 0;
while (1) {
char key = keypad.getKey();
if ('0' <= key && key <= '9' && i < 3) {
// If it's a number AND we have space left, add to our string
buffer[i] = key;
i++;
} else if ('#' == key && i > 0) {
// If it's a * or #, end
// Null terminate
buffer[i] = 0;
int value = atoi(buffer); // Convert to an integer
break;
}
}
return atoi(buffer);
}
// FUNCTION FOR RPM MEASUREMENT
void rpmMeasure() {
// RPM Measurement
currentstate = digitalRead(dataIN); // Read IR sensor state
if (prevstate != currentstate) {
// If there is change in input
if (currentstate == HIGH) {
// If input only changes from LOW to HIGH
duration = (micros() - prevmillis); // Time difference between revolution in microsecond
rpm = (60000000 / duration); // rpm = (1/ time millis)*1000*1000*60;
prevmillis = micros(); // store time for next revolution calculation
}
}
prevstate = currentstate; // store this scan (prev scan) data for next scan
lcd.setCursor(10, 3);
lcd.print(rpm);
}
// FUNCTION FOR MOTOR SPINNING ACCORDING TO TIME AND SPEED
void motorspin() {
char key = keypad.getKey();
unsigned long currentMillis = millis();
int idleValue = 0;
static enum { IDLE , STAGE0, STAGE1, STAGE2, STAGE3 } spinningstate = IDLE;
switch (spinningstate) {
case IDLE:
if (key == '*') {
Serial.print(key);
spinningstate = STAGE0;
}
break;
case STAGE0:
myservo.write(stage1speed);
Serial.print(stage1speed);
previousMillis = currentMillis;
spinningstate = STAGE1;
break;
case STAGE1:
if (currentMillis - previousMillis >= stage1time * interval) {
myservo.write(stage2speed);
Serial.print(stage2speed);
previousMillis = currentMillis;
spinningstate = STAGE2;
}
break;
case STAGE2:
if (currentMillis - previousMillis >= stage2time * interval) {
myservo.write(stage3speed);
Serial.print(stage3speed);
previousMillis = currentMillis;
spinningstate = STAGE3;
}
break;
case STAGE3:
if (currentMillis - previousMillis >= stage3time * interval) {
myservo.write(idleValue);
Serial.print(idleValue);
spinningstate = IDLE;
}
break;
default:
spinningstate = IDLE;
break;
}
}
// MAIN LOOP
void loop() {
char key = keypad.getKey();
switch (systemstate) {
case enter_values:
enter_speed_time();
systemstate = spin;
break;
case spin:
rpmMeasure();
motorspin();
if (key == '#') {
Serial.print(key);
systemstate = finish;
}
break;
case finish:
lcd.clear();
delay(1000);
systemstate = enter_values;
break;
default:
systemstate = enter_values;
}
delay(1);
}
to convert value from 0-180 to 0-9000
map(value,0,180,0,9000)
to convert from 0-9000 to 0-180
map(value,0,9000,0,180)
I'm currently doing a project on an Arduino Uno. The project is based on receiving an IR Signal from an IR Remote and then based on the signal received, perform other operations.
The problem is that the signal gets reset every time. I want to store the value received from the IR Remote and then resets it if detects another pulse.
Here is my code :
int brojac = 0;
int pinData = 10;
unsigned long lengthHeader;
unsigned long bit;
int byteValue;
int vrime = 1000 ;
int storeValue = 0;
void setup()
{
Serial.begin(9600);
pinMode(pinData, INPUT);
}
void loop() {
lengthHeader = pulseIn(pinData, LOW);
if (lengthHeader > 1500)
{
for (int i = 1; i <= 32; i++) {
bit = pulseIn(pinData, HIGH);
if (i > 16 && i <= 24)
if (bit > 1000)
byteValue = byteValue + (1 << (i - 17));
}
}
Serial.print("byteValue = ");
Serial.println(byteValue);
if(byteValue == 66){
digitalWrite(11,HIGH);
}
else{
digitalWrite(11,LOW);
}
delay(vrime);
byteValue = 0;
delay(250);
}
I got the answer by storing the value in a variable until a new variable is detected.
int pinData = 10;
int led = 11;
unsigned long lengthHeader;
unsigned long bit;
int byteValue;
int storeValue = 0;
int previousValue = 0;
void setup()
{
Serial.begin(9600);
pinMode(pinData, INPUT);
pinMode(led, LOW);
}
void loop() {
lengthHeader = pulseIn(pinData, LOW);
if (lengthHeader > 1500)
{
for (int i = 1; i <= 32; i++) {
bit = pulseIn(pinData, HIGH);
if (i > 16 && i <= 24)
if (bit > 1000)
byteValue = byteValue + (1 << (i - 17));
}
}
Serial.print("byteValue = ");
Serial.println(byteValue);
**storeValue = byteValue;
if (storeValue != 0){
previousValue = storeValue;
}
Serial.print("Previous value = ");
Serial.println(previousValue);**
byteValue = 0;
delay(500);
}