Doppler radar (HB100) Arduino code : Why do we use bit-shifting? - arduino

I've been working on my doppler radar speed project for a while. I found this very helpful link and the code below:
// Based on the Adafruit Trinket Sound-Reactive LED Color Organ
// http://learn.adafruit.com/trinket-sound-reactive-led-color-organ/code
#define RADAR A5 // RADAR inut is attached to A7
#define MICRODELAY 100 // 100microseconds ~10000hz
#define MAXINDEX 1024 // 10 bits
#define TOPINDEX 1023 // 10 bits
byte collect[MAXINDEX];
int mean;
int minimum;
int maximum;
int hysteresis; // 1/16 of max-min
bool currentphase; // are value above mean + hysteresis;
int lastnull; // index for last null passing value
int prevnull; // index for previous null passing value
int deltaindex;
int deltadeltaindex;
int index;
bool phasechange = false;
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
while (!Serial) {}
index = 0;
mean = 0;
maximum = 255;
minimum = 0;
hysteresis = 0;
currentphase = false;
lastnull = 0;
prevnull = 0;
Serial.print("deltadeltaindex");
Serial.print("\t");
Serial.print("deltaindex");
Serial.print("\t");
Serial.println("delta");
}
void loop() {
int newVal = analogRead(RADAR); // Raw reading from amplified radar
mean -= (collect[index] >> 2);
mean += (newVal >> 2);
collect[index]= newVal;
minimum = newVal < minimum ? newVal : minimum + 1;
maximum = newVal > maximum ? newVal : maximum - 1;
hysteresis = abs(maximum - minimum) >> 5;
if(newVal > (mean + hysteresis))
{
if(false == currentphase)
{
currentphase = true;
phasechange = true;
}
}
else if(newVal < (mean - hysteresis))
{
if(currentphase)
{
currentphase = false;
phasechange = true;
}
}
if(phasechange)
{
prevnull = lastnull;
lastnull = index;
int delta = (prevnull > lastnull) ?
(lastnull - prevnull + MAXINDEX) :
(lastnull - prevnull);
deltadeltaindex = abs(deltaindex - delta);
deltaindex = delta;
Serial.print(deltadeltaindex);
Serial.print("\t");
Serial.print(deltaindex);
Serial.print("\t");
Serial.println(delta);
}
index = index == TOPINDEX ? 0 : index + 1;
phasechange = false;
//delayMicroseconds(10);
}
I tried it out on my Arduino with HB100(model with breakout board), and it works just fine.
However, what I really wanted to do was to understand the mechanism behind the code. I read some articles on hysteresis and bit-shifting, but I simply cannot understand why the programmer here used bit-shifting.
What would mean -= (collect[index] >> 2); and mean += (newVal >> 2); do to the values exactly?
Help will be appreciated.

Related

MPU6050 FIFO overflow and freezing problems

Im using the sensor MPU6050 to control movements of my robotic arm. The codes work fine when it is a standalone program but i keep encountering 'FIFO overflow' when the codes are complied into the main program. This is the code that i am using.
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include "I2Cdev.h"
#include "MPU6050_6Axis_MotionApps20.h"
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
#include "Wire.h"
#endif
MPU6050 mpu;
RF24 radio(9, 8); // CE, CSN
const byte address[6] = "00001";
const int AccReadings = 10;
//Wrist Roll
int DataX[AccReadings];
int WRIndex = 0;
int WRtotal = 0;
int WRaverage = 0;
//Wrist Pitch
int DataY[AccReadings];
int WPIndex = 0;
int WPtotal = 0;
int WPaverage = 0;
//Shoulder Lift
int DataY2[AccReadings];
int SLIndex = 0;
int SLtotal = 0;
int SLaverage = 0;
//Elbow Lift
int ELaverage = 0;
//Arm Rotation
int ARaverage = 0;
float correct;
#define OUTPUT_READABLE_YAWPITCHROLL
#define INTERRUPT_PIN 2
bool blinkState = false;
// MPU control/status vars
bool dmpReady = false; // set true if DMP init was successful
uint8_t mpuIntStatus; // holds actual interrupt status byte from MPU
uint8_t devStatus; // return status after each device operation (0 = success, !0 = error)
uint16_t packetSize; // expected DMP packet size (default is 42 bytes)
uint16_t fifoCount; // count of all bytes currently in FIFO
uint8_t fifoBuffer[64]; // FIFO storage buffer
// orientation/motion vars
Quaternion q; // [w, x, y, z] quaternion container
VectorInt16 aa; // [x, y, z] accel sensor measurements
VectorInt16 aaReal; // [x, y, z] gravity-free accel sensor measurements
VectorInt16 aaWorld; // [x, y, z] world-frame accel sensor measurements
VectorFloat gravity; // [x, y, z] gravity vector
float euler[3]; // [psi, theta, phi] Euler angle container
float ypr[3]; // [yaw, pitch, roll] yaw/pitch/roll container and gravity vector
struct Sensor_Data
{
int WristRoll;
int WristPitch;
int ShoulderLift;
int ElbowLift;
int ArmRotation;
};
Sensor_Data data;
//Interrupt Detection
volatile bool mpuInterrupt = false;
void dmpDataReady()
{
mpuInterrupt = true;
}
void setup()
{
radio.begin();
radio.openWritingPipe(address);
radio.setPALevel(RF24_PA_MIN);
radio.stopListening();
//Zero-fill Arrays
for (int i = 0; i < AccReadings; i++)
{
DataX[i] = 0;
}
for (int j = 0; j < AccReadings; j++)
{
DataY[j] = 0;
}
for (int k = 0; k < AccReadings; k++)
{
DataY2[k] = 0;
}
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
Wire.begin();
Wire.setClock(400000);
#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
Fastwire::setup(400, true);
#endif
Serial.begin(115200);
while (!Serial);
mpu.initialize();
pinMode(INTERRUPT_PIN, INPUT);
devStatus = mpu.dmpInitialize();
mpu.setXGyroOffset(49);
mpu.setYGyroOffset(-18);
mpu.setZGyroOffset(9);
mpu.setZAccelOffset(4427);
if (devStatus == 0)
{
mpu.setDMPEnabled(true);
attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), dmpDataReady, RISING);
mpuIntStatus = mpu.getIntStatus();
dmpReady = true;
packetSize = mpu.dmpGetFIFOPacketSize();
}
else
{
// ERROR!
// 1 = initial memory load failed
// 2 = DMP configuration updates failed
// (if it's going to break, usually the code will be 1)
// Serial.print(F("DMP Initialization failed (code "));
//Serial.print(devStatus);
//Serial.println(F(")"));
}
}
void loop()
{
/*smoothWR();
movementWR();
smoothWP();
movementWP();
smoothSL();
movementSL();*/
ElbowMovement();
radio.write(&data, sizeof(Sensor_Data));
}
void smoothWR()
{
WRtotal = WRtotal - DataX[WRIndex];
DataX[WRIndex] = analogRead(A0);
WRtotal = WRtotal + DataX[WRIndex];
WRIndex = WRIndex + 1;
if (WRIndex >= AccReadings)
{
WRIndex = 0;
}
WRaverage = WRtotal / AccReadings;
//Serial.println(WRaverage);
}
void movementWR()
{
WRaverage = map(WRaverage, 278, 419, 0, 180);
data.WristRoll = constrain(WRaverage, 0, 180);
//Serial.println(data.WristRoll);
}
void smoothWP()
{
WPtotal = WPtotal - DataY[WPIndex];
DataY[WPIndex] = analogRead(A1);
WPtotal = WPtotal + DataY[WPIndex];
WPIndex = WPIndex + 1;
if (WPIndex >= AccReadings)
{
WPIndex = 0;
}
WPaverage = WPtotal / AccReadings;
//Serial.println(WPaverage);
}
void movementWP()
{
WPaverage = map(WPaverage, 280, 421, 0 , 135);
data.WristPitch = constrain(WPaverage, 0, 135);
//Serial.println(data.WristPitch);
}
void smoothSL()
{
SLtotal = SLtotal - DataY2[SLIndex];
DataY2[SLIndex] = analogRead(A2);
SLtotal = SLtotal + DataY2[SLIndex];
SLIndex = SLIndex + 1;
if (SLIndex >= AccReadings)
{
SLIndex = 0;
}
SLaverage = SLtotal / AccReadings;
//Serial.println(SLaverage);
}
void movementSL()
{
SLaverage = map(SLaverage, 410, 270, 0 , 180);
data.ShoulderLift = constrain(SLaverage, 35, 180);
//Serial.println(data.ShoulderLift);
}
void ElbowMovement()
{
// if programming failed, don't try to do anything
if (!dmpReady) return;
// wait for MPU interrupt or extra packet(s) available
while (!mpuInterrupt && fifoCount < packetSize)
{
if (mpuInterrupt && fifoCount < packetSize)
{
// try to get out of the infinite loop
fifoCount = mpu.getFIFOCount();
}
}
// reset interrupt flag and get INT_STATUS byte
mpuInterrupt = false;
mpuIntStatus = mpu.getIntStatus();
// get current FIFO count
fifoCount = mpu.getFIFOCount();
// check for overflow (this should never happen unless our code is too inefficient)
if ((mpuIntStatus & _BV(MPU6050_INTERRUPT_FIFO_OFLOW_BIT)) || fifoCount >= 1024)
{
// reset so we can continue cleanly
mpu.resetFIFO();
fifoCount = mpu.getFIFOCount();
Serial.println(F("FIFO overflow!"));
// otherwise, check for DMP data ready interrupt (this should happen frequently)
}
else if (mpuIntStatus & _BV(MPU6050_INTERRUPT_DMP_INT_BIT))
{
// wait for correct available data length, should be a VERY short wait
while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount();
// read a packet from FIFO
mpu.getFIFOBytes(fifoBuffer, packetSize);
// track FIFO count here in case there is > 1 packet available
// (this lets us immediately read more without waiting for an interrupt)
fifoCount -= packetSize;
// Get Yaw, Pitch and Roll values
#ifdef OUTPUT_READABLE_YAWPITCHROLL
mpu.dmpGetQuaternion(&q, fifoBuffer);
mpu.dmpGetGravity(&gravity, &q);
mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
// Yaw, Pitch, Roll values - Radians to degrees
ypr[0] = ypr[0] * 180 / M_PI;
ypr[1] = ypr[1] * 180 / M_PI;
ypr[2] = ypr[2] * 180 / M_PI;
// Skip 300 readings (self-calibration process)
if (int l = 0; l <= 300) {
correct = ypr[0]; // Yaw starts at random value, so we capture last value after 300 readings
l++;
}
// After 300 readings
else {
ypr[0] = ypr[0] - correct; // Set the Yaw to 0 deg - subtract the last random Yaw value from the currrent value to make the Yaw 0 degrees
// Map the values of the MPU6050 sensor from -90 to 90 to values suatable for the servo control from 0 to 180
ELaverage = map(ypr[0], -90, 90, 0, 180);
data.ElbowLift = constrain(ELaverage, 30, 110);
ARaverage = map(ypr[1], -90, 90, 0, 180);
data.ArmRotation = constrain(ARaverage, 0, 180);
//Serial.println(data.ElbowLift);
Serial.println(ypr[1]);
}
#endif
}
}
Is there any ways to get rid of the FIFO overflow? Also When i tried to used Jeff Rowberg's example codes MPU6050_DMP6 the program will freeze after a few seconds. Is there any solution to that? These are the example codes that i am using.
#include "I2Cdev.h"
#include "MPU6050_6Axis_MotionApps20.h"
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
#include "Wire.h"
#endif
MPU6050 mpu;
float correct;
int j = 0;
#define OUTPUT_READABLE_YAWPITCHROLL
#define INTERRUPT_PIN 2
bool blinkState = false;
// MPU control/status vars
bool dmpReady = false; // set true if DMP init was successful
uint8_t mpuIntStatus; // holds actual interrupt status byte from MPU
uint8_t devStatus; // return status after each device operation (0 = success, !0 = error)
uint16_t packetSize; // expected DMP packet size (default is 42 bytes)
uint16_t fifoCount; // count of all bytes currently in FIFO
uint8_t fifoBuffer[64]; // FIFO storage buffer
// orientation/motion vars
Quaternion q; // [w, x, y, z] quaternion container
VectorInt16 aa; // [x, y, z] accel sensor measurements
VectorInt16 aaReal; // [x, y, z] gravity-free accel sensor measurements
VectorInt16 aaWorld; // [x, y, z] world-frame accel sensor measurements
VectorFloat gravity; // [x, y, z] gravity vector
float euler[3]; // [psi, theta, phi] Euler angle container
float ypr[3]; // [yaw, pitch, roll] yaw/pitch/roll container and gravity vector
//Interrupt Detection
volatile bool mpuInterrupt = false; // indicates whether MPU interrupt pin has gone high
void dmpDataReady() {
mpuInterrupt = true;
}
void setup()
{
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
Wire.begin();
Wire.setClock(400000);
#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
Fastwire::setup(400, true);
#endif
Serial.begin(38400);
while (!Serial);
mpu.initialize();
pinMode(INTERRUPT_PIN, INPUT);
devStatus = mpu.dmpInitialize();
mpu.setXGyroOffset(17);
mpu.setYGyroOffset(-69);
mpu.setZGyroOffset(27);
mpu.setZAccelOffset(1551);
if (devStatus == 0)
{
mpu.setDMPEnabled(true);
attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), dmpDataReady, RISING);
mpuIntStatus = mpu.getIntStatus();
dmpReady = true;
packetSize = mpu.dmpGetFIFOPacketSize();
}
else
{
// ERROR!
// 1 = initial memory load failed
// 2 = DMP configuration updates failed
// (if it's going to break, usually the code will be 1)
// Serial.print(F("DMP Initialization failed (code "));
//Serial.print(devStatus);
//Serial.println(F(")"));
}
}
void loop()
{
if (!dmpReady) return;
if (mpu.dmpGetCurrentFIFOPacket(fifoBuffer))
{
#ifdef OUTPUT_READABLE_YAWPITCHROLL
// display Euler angles in degrees
mpu.dmpGetQuaternion(&q, fifoBuffer);
mpu.dmpGetGravity(&gravity, &q);
mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
if (j <= 300)
{
correct = ypr[0]; // Yaw starts at random value, so we capture last value after 300 readings
j++;
}
else
{
ypr[0] = ypr[0] - correct;
Serial.print("ypr\t");
Serial.print(ypr[0] * 180/M_PI);
Serial.print("\t");
Serial.print(ypr[1] * 180/M_PI);
Serial.print("\t");
Serial.println(ypr[2] * 180/M_PI);
}
#endif
}
}
You're using DMP (Digital Motion Processor) with mean calculation running on the MPU itself, this gives more precise and less CPU consumption but you need to update the FIFO frequently or the track goes wrong.
Encountering 'FIFO overflow' means your loop code was too slow, you should increase the speed of another task in your loop code. Or just use other code that not use the DMP.

Arduino loop stops after for loop in called function

I am trying to make a radio controlled car which reacts to the frequency of music. The Loop works as it should and it gives me the correct frequency. The function berekenGrootte works too. This gives me the size of the frequency (max frequency - min frequency). But as soon as I want to use the function verdeel() which divides the size of the frequency in 10 to make the car move smoother it does it one or two times and then I don't get any feedback anymore in my serial monitor. Do I use too much Serial.print or do I need to restart the loop after the for loop in the second function?
#include <FreqMeasure.h>
void setup()
{
Serial.begin(57600);
pinMode(3, OUTPUT);
pinMode(5, OUTPUT);
pinMode(2, OUTPUT);
pinMode(4, OUTPUT);
FreqMeasure.begin();
}
double sum = 0;
int count = 0;
float lowest = 50;
float highest = 0;
float grootte = 50;
float b[9][1];
void loop()
{
if (FreqMeasure.available()) {
// average several reading together
sum = sum + FreqMeasure.read();
count = count + 1;
if (count > 30) {
float frequency = FreqMeasure.countToFrequency(sum / count);
Serial.println(frequency);
sum = 0;
count = 0;
if (frequency < lowest) {
lowest = frequency;
Serial.print("new lowest: ");
Serial.println(lowest);
berekenGrootte();
}
else if (frequency > highest) {
highest = frequency;
Serial.print("new highest: ");
Serial.println(highest);
berekenGrootte();
}
/*if(frequency > 1000){
digitalWrite(3,HIGH);
delay(1000);
digitalWrite(3,LOW);
}
else{
digitalWrite(5,HIGH);
delay(1000);
digitalWrite(5,LOW);
}*/
}
}
}
void berekenGrootte()
{
grootte = highest - lowest;
Serial.print("new grootte: ");
Serial.println(grootte);
verdeel();
}
void verdeel()
{
float plength = grootte / 10;
b[0][0] = lowest;
b[0][1] = lowest + plength;
Serial.print("low: ");
Serial.println(b[0][0]);
Serial.print("high: ");
Serial.println(b[0][1]);
float startvalue = lowest + plength;
for (int i = 1; i < 10; i++) {
b[i][0] = startvalue;
b[i][1] = startvalue + plength;
startvalue = startvalue + plength;
Serial.print(i);
Serial.print(" low: ");
Serial.println(b[i][0]);
Serial.print(i);
Serial.print(" high: ");
Serial.println(b[i][1]);
}
}
You're overstepping the bounds of your b array.
float b[9][1];
The array is only 9 * 1.
void verdeel()
{
float plength = grootte / 10;
b[0][0] = lowest;
b[0][1] = lowest + plength;
So there is no element b[0][1]. The second number can only go up to 0 since the array is size 1 in that dimension. An array of size 1 is pretty useless as an array.
You have the same problem here in this loop at the end of that function:
for (int i = 1; i < 10; i++) {
b[i][0] = startvalue;
b[i][1] = startvalue + plength;
This for loop allows i to go to 9 which is too large for the array.

Arduino LED Controller hanging at startup

I'm trying to code an LED controller that controls the intensity via PWM. However, my issue is that I can't even get to the loop portion, it seems to hang at when I declare my class. I've tried checking to see if any of my functions in my class are causing the issues, but since I can't even get to loop, there must be something wrong within the class. I've written the class and placed it into a library called LED.
The code is somewhat long, but here it is:
#ifndef LED_H
#define LED_H
#include <LiquidCrystal.h>
#include <Button.h>
#include <EEPROM.h>
#include <TimeLib.h>
#include <PWM.h>
class LED
{
public:
LED();
int read_encoder(); //Reads rotary encoder
void clearLCD();
void setAllLed();
void printLCD();
void setOneLed(int);
int setLed(int, // current time in minutes
int, // pin for this channel of LEDs
int, // start time for this channel of LEDs
int, // photoperiod for this channel of LEDs
int, // fade duration for this channel of LEDs
int, // max value for this channel
bool // true if the channel is inverted
);
void menuWizard();
int subMenuWizard(int, int, bool, bool);
void displayMainMenu();
void printMins(int, bool);
void printHMS(byte,byte,byte);
long EEPROMReadlong(long);
void EEPROMWritelong(int, long);
bool pressSelect();
bool pressBack();
void rotateCheck(int&, int, int);
//variables for the LED channels
int minCounter = 0; // counter that resets at midnight.
int oldMinCounter = 0; // counter that resets at midnight.
int ledPins[5]={2,3,5,6,7};
int ledVal[5]={0,0,0,0,0};
// Variables making use of EEPROM memory:
int variablesList[20];
bool invertedLEDs[5]={false,false,false,false,false};
//Backlight Variables
unsigned long backlightIdleMs = 0;
private:
};
#endif // LED_H
And here is the .cpp file:
#define LCD_RS 35 // RS pin
#define LCD_ENABLE 34 // enable pin
#define LCD_DATA4 33 // d4 pin
#define LCD_DATA5 32 // d5 pin
#define LCD_DATA6 31 // d6 pin
#define LCD_DATA7 30 // d7 pin
#define LCD_BACKLIGHT 9 // backlight pin
// Backlight config
#define BACKLIGHT_DIM 10 // PWM value for backlight at idle
#define BACKLIGHT_ON 70 // PWM value for backlight when on
#define BACKLIGHT_IDLE_MS 10000 // Backlight idle delay
#define ENC_A 14
#define ENC_B 15
#define ENC_PORT PINC
#include <LiquidCrystal.h>
#include <Button.h>
#include <EEPROM.h>
#include <TimeLib.h>
#include <PWM.h>
#include "LED.h"
LiquidCrystal lcd(LCD_RS, LCD_ENABLE, LCD_DATA4, LCD_DATA5, LCD_DATA6, LCD_DATA7);
Button goBack=Button(12, PULLDOWN);
Button select=Button(13, PULLDOWN);
LED::LED()
{
InitTimersSafe();
pinMode(LCD_BACKLIGHT, OUTPUT);
lcd.begin(16, 2);
digitalWrite(LCD_BACKLIGHT, HIGH);
lcd.print("sEx LED, V1");
clearLCD();
delay(5000);
analogWrite(LCD_BACKLIGHT, BACKLIGHT_DIM);
if (variablesList[0] > 1440 || variablesList[0] < 0) {
variablesList[0] = 720; // minute to start this channel.
variablesList[1] = 400; // photoperiod in minutes for this channel.
variablesList[2] = 100; // max intensity for this channel, as a percentage
variablesList[3] = 100; // duration of the fade on and off for sunrise and sunset for
// this channel.
variablesList[4] = 720;
variablesList[5] = 400;
variablesList[6] = 100;
variablesList[7] = 100;
variablesList[8] = 720;
variablesList[9] = 400;
variablesList[10] = 100;
variablesList[11] = 100;
variablesList[12] = 720;
variablesList[13] = 400;
variablesList[14] = 100;
variablesList[15] = 100;
variablesList[16] = 720;
variablesList[17] = 400;
variablesList[18] = 100;
variablesList[19] = 100;
}
else {
variablesList[0] = EEPROMReadlong(0); // minute to start this channel.
variablesList[1] = EEPROMReadlong(4); // photoperiod in minutes for this channel.
variablesList[2] = EEPROMReadlong(8); // max intensity for this channel, as a percentage
variablesList[3] = EEPROMReadlong(12); // duration of the fade on and off for sunrise and sunset for
// this channel.
variablesList[4] = EEPROMReadlong(16);
variablesList[5] = EEPROMReadlong(20);
variablesList[6] = EEPROMReadlong(24);
variablesList[7] = EEPROMReadlong(28);
variablesList[8] = EEPROMReadlong(32);
variablesList[9] = EEPROMReadlong(36);
variablesList[10] = EEPROMReadlong(40);
variablesList[11] = EEPROMReadlong(44);
variablesList[12] = EEPROMReadlong(48);
variablesList[13] = EEPROMReadlong(52);
variablesList[14] = EEPROMReadlong(56);
variablesList[15] = EEPROMReadlong(60);
variablesList[16] = EEPROMReadlong(64);
variablesList[17] = EEPROMReadlong(68);
variablesList[18] = EEPROMReadlong(72);
variablesList[19] = EEPROMReadlong(76);
}
}
void LED::printLCD(){lcd.print("test");clearLCD();delay(2000);lcd.print("testing");clearLCD();}
bool LED::pressSelect(){
if (select.uniquePress()){return 1;}
else {return 0;}
}
bool LED::pressBack(){
if (goBack.uniquePress()){return 1;}
else {return 0;}
}
void LED::clearLCD(){
lcd.clear();
}
void LED::displayMainMenu(){
oldMinCounter = minCounter;
minCounter = hour() * 60 + minute();
for (int i=0;i<17;i=i+4){
if (variablesList[i+3] > variablesList[i+1] / 2 && variablesList[i+1] > 0) {
variablesList[i+3] = variablesList[i+1] / 2;
}
if (variablesList[i+3] < 1) {
variablesList[i+3] = 1;
}
}
//check & set any time functions
if (minCounter > oldMinCounter) {
lcd.clear();
}
lcd.setCursor(0, 0);
printHMS(hour(), minute(), second());
lcd.setCursor(0, 1);
lcd.print(ledVal[0]);
lcd.setCursor(4, 1);
lcd.print(ledVal[1]);
lcd.setCursor(8, 1);
lcd.print(ledVal[2]);
}
int LED::read_encoder()
{
static int enc_states[] = {0,-1,1,0,1,0,0,-1,-1,0,0,1,0,1,-1,0};
static int old_AB = 0;
/**/
old_AB <<= 2; //remember previous state
old_AB |= ( ENC_PORT & 0x03 ); //add current state
return ( enc_states[( old_AB & 0x0f )]);
}
int LED::setLed(int mins, // current time in minutes
int ledPin, // pin for this channel of LEDs
int start, // start time for this channel of LEDs
int period, // photoperiod for this channel of LEDs
int fade, // fade duration for this channel of LEDs
int ledMax, // max value for this channel
bool inverted // true if the channel is inverted
) {
int val = 0;
//fade up
if (mins > start || mins <= start + fade) {
val = map(mins - start, 0, fade, 0, ledMax);
}
//fade down
if (mins > start + period - fade && mins <= start + period) {
val = map(mins - (start + period - fade), 0, fade, ledMax, 0);
}
//off or post-midnight run.
if (mins <= start || mins > start + period) {
if ((start + period) % 1440 < start && (start + period) % 1440 > mins )
{
val = map((start + period - mins) % 1440, 0, fade, 0, ledMax);
}
else
val = 0;
}
if (val > ledMax) {
val = ledMax;
}
if (val < 0) {
val = 0;
}
if (inverted) {
pwmWrite(ledPin, map(val, 0, 100, 255, 0));
}
else {
pwmWrite(ledPin, map(val, 0, 100, 0, 255));
}
return val;
}
void LED::printMins(int mins, //time in minutes to print
bool ampm //print am/pm?
) {
int hr = (mins % 1440) / 60;
int mn = mins % 60;
if (hr < 10) {
lcd.print(" ");
}
lcd.print(hr);
lcd.print(":");
if (mn < 10) {
lcd.print("0");
}
lcd.print(mn);
}
void LED::printHMS (byte hr,
byte mn,
byte sec //time to print
)
{
if (hr < 10) {
lcd.print(" ");
}
lcd.print(hr, DEC);
lcd.print(":");
if (mn < 10) {
lcd.print("0");
}
lcd.print(mn, DEC);
lcd.print(":");
if (sec < 10) {
lcd.print("0");
}
lcd.print(sec, DEC);
}
//EEPROM write functions
long LED::EEPROMReadlong(long address)
{
//Read the 4 bytes from the eeprom memory.
long four = EEPROM.read(address);
long three = EEPROM.read(address + 1);
long two = EEPROM.read(address + 2);
long one = EEPROM.read(address + 3);
//Return the recomposed long by using bitshift.
return ((four << 0) & 0xFF) + ((three << 8) & 0xFFFF) + ((two << 16) & 0xFFFFFF) + ((one << 24) & 0xFFFFFFFF);
}
void LED::EEPROMWritelong(int address, long value)
{
//Decomposition from a long to 4 bytes by using bitshift.
//One = Most significant -> Four = Least significant byte
byte four = (value & 0xFF);
byte three = ((value >> 8) & 0xFF);
byte two = ((value >> 16) & 0xFF);
byte one = ((value >> 24) & 0xFF);
//Write the 4 bytes into the eeprom memory.
EEPROM.write(address, four);
EEPROM.write(address + 1, three);
EEPROM.write(address + 2, two);
EEPROM.write(address + 3, one);
}
void LED::setAllLed(){
int j=0;
for (int i=0;i<17;i=i+4){
int a=i;int b=i+1;int c=i+2;int d=i+3;
ledVal[j] = setLed(minCounter, ledPins[j], variablesList[a], variablesList[b], variablesList[c], variablesList[d], invertedLEDs[j]);
j++;
}
}
void LED::setOneLed(int channel){
int j=channel;
int i=0;
if(channel==1){i+=4;}
if(channel==2){i+=8;}
if(channel==3){i+=12;}
if(channel==4){i+=16;}
int a=i;int b=i+1;int c=i+2;int d=i+3;
ledVal[j] = setLed(minCounter, ledPins[j], variablesList[a], variablesList[b], variablesList[c], variablesList[d], invertedLEDs[j]);
}
void LED::rotateCheck(int& menuCount, int minMenu, int maxMenu){
while (menuCount!=0){
int rotateCount;
rotateCount=read_encoder();
if (rotateCount) {
menuCount+=rotateCount;
if (menuCount<minMenu){menuCount==maxMenu;}
if (menuCount>maxMenu){menuCount==minMenu;}
clearLCD();
}
}
}
void LED::menuWizard(){
int menuCount=1;
String menuList[6]={"Time","LED Max","LED Start","LED End","Fade Length","Ch Override"};
String channelList[5]={"1","2","3","4","5"};
while (menuCount!=0){
rotateCheck(menuCount,1,6);
lcd.setCursor(0, 0);
lcd.print(menuList[menuCount-1]);
clearLCD();
if (goBack.isPressed()){
menuCount=0;
}
if (pressSelect() && menuCount!=0){
int timeMode=1;
int channelCount=0;
bool goBack=0;
while (goBack!=1){
if (menuCount==1){
if (pressSelect()){
timeMode++;
if (timeMode>2){timeMode=1;}
}
int timeAdjDetect=read_encoder();
if (timeMode==1){
if (timeAdjDetect){
if (timeAdjDetect>0){adjustTime(SECS_PER_HOUR);}
if (timeAdjDetect<0) {adjustTime(-SECS_PER_HOUR);}
}
lcd.setCursor(0, 0);
lcd.print("Set Time: Hrs");
lcd.setCursor(0, 1);
printHMS(hour(), minute(), second());
}
else{
if (timeAdjDetect){
if (timeAdjDetect>0){adjustTime(SECS_PER_MIN);}
if (timeAdjDetect<0) {adjustTime(-SECS_PER_MIN);}
}
lcd.setCursor(0, 0);
lcd.print("Set Time: Mins");
lcd.setCursor(0, 1);
printHMS(hour(), minute(), second());
}
clearLCD();
}
else{
rotateCheck(channelCount,0,4);
lcd.setCursor(0,0);
lcd.print("Select Channel");
lcd.setCursor(0,1);
lcd.print(channelList[channelCount]);
clearLCD();
if (pressSelect()){
if (menuCount==2){
subMenuWizard(2,channelCount,0,0);
}
if (menuCount==3){
subMenuWizard(0,channelCount,1,0);
}
if (menuCount==4){
subMenuWizard(1,channelCount,1,1);
}
if (menuCount==5){
subMenuWizard(3,channelCount,1,0);
}
}
}
if (pressBack()){goBack=1;}
}
}
}
for (int i=0;i<20;i++){
int j=0;
EEPROMWritelong(j, variablesList[i]);
j+=4;
}
}
int LED::subMenuWizard(int i, int channel, bool time, bool truetime){
if (channel==1){i=i+4;}
if (channel==2){i=i+8;}
if (channel==3){i=i+12;}
if (channel==4){i=i+16;}
while (!pressBack()){
if (time==0){
rotateCheck(variablesList[i],0,100);
lcd.setCursor(0,0);
lcd.print("Set:");
lcd.setCursor(0,1);
lcd.print(variablesList[i]);
setOneLed(channel);
clearLCD();
}
else{
if (truetime){
rotateCheck(variablesList[i],0,1439);
lcd.setCursor(0,0);
lcd.print("Set:");
lcd.setCursor(0,1);
printMins(variablesList[i] + variablesList[i-1], true);
clearLCD();
}
else {
rotateCheck(variablesList[i],0,1439);
lcd.setCursor(0,0);
lcd.print("Set:");
lcd.setCursor(0,1);
printMins(variablesList[i], true);
clearLCD();
}
setOneLed(channel);
}
}
}
and finally, the .ino file:
#define LCD_BACKLIGHT 9 // backlight pin
#define BACKLIGHT_DIM 10 // PWM value for backlight at idle
#define BACKLIGHT_ON 70 // PWM value for backlight when on
#define BACKLIGHT_IDLE_MS 10000 // Backlight idle delay
#include <LED.h>
//Initialize buttons
int buttonCount = 1;
LED main;
void setup() {
};
void loop() {
/* main.setAllLed();
//turn the backlight off and reset the menu if the idle time has elapsed
if (main.backlightIdleMs + BACKLIGHT_IDLE_MS < millis() && main.backlightIdleMs > 0 ) {
analogWrite(LCD_BACKLIGHT, BACKLIGHT_DIM);
main.clearLCD();
main.backlightIdleMs = 0;
}
if (buttonCount == 1) {
main.displayMainMenu();
}
if (buttonCount == 2) {
main.menuWizard();
buttonCount = 1;
}
*/
main.printLCD();
};
Also, in the loop portion, I've commented the part of code that is intended to run, and I'm running a function that tests to see if I've successfully entered the loop by printing "test" on screen.
I'm using a Mega for this.
LED::LED()
{
InitTimersSafe();
pinMode(LCD_BACKLIGHT, OUTPUT);
lcd.begin(16, 2);
digitalWrite(LCD_BACKLIGHT, HIGH);
lcd.print("sEx LED, V1");
clearLCD();
delay(5000);
analogWrite(LCD_BACKLIGHT, BACKLIGHT_DIM);
You have to understand that this constructor is running when the object is created and that is probably before init() is run from main. So the hardware isn't ready at that point and pinMode and digitalWrite and stuff isn't going to work. The lcd code can't really work there and I bet that is the part that is hanging things.
A constructor should only do things like initialize variables. Any code that relies on the hardware should go into a begin() or init() or whatever method that you can call from setup once it is safe to do those things. The Serial object is a great example of another class that has to do this.

Unexpected behavior in my RGB-strip driver code

I'm getting wrong output on the pins 9, 10 and 11. They are meant to be inputs for my RGB strip driver circuit. Which is basically an array of NPN transistors pulling current from the strip.
The basic idea is to get only 2 controls to set R, G, B and brightness. I'm using a button and a potenciometer. Potenciometer is used to set the value and the button to skip to next value setting. There is one setting state which is like the default one. It is the one to set the brightness and I will be using this most of the time. The othe ones are for setting the colors and when in one of those setting the strip will be blinking in between only the color I'm currently setting and the result with alle three colors set. The whole code was working just fine until I added the brightness setting and I think that I am kinda lost in my own code.
I even added a serial to read the outputs but I don't understand why are the numbers the way they are :(
int pinR = 9;
int pinG = 10;
int pinB = 11;
int potPin = A0;
const int buttonPin = 2;
int brightR = 0;
int brightG = 0;
int brightB = 0;
int brightness = 50; //
int R;
int G;
int B;
int potValue = 0;
int blinky = 0;
boolean blinking = false;
int buttonState;
int lastButtonState = LOW;
long lastDebounceTime = 0;
long debounceDelay = 50;
int setting = 0; //0=R 1=G 2=B 3=Brightness
void setup() {
// put your setup code here, to run once:
pinMode(pinR, OUTPUT);
pinMode(pinG, OUTPUT);
pinMode(pinB, OUTPUT);
Serial.begin(9600);
}
void RGBset(int r, int g, int b){
analogWrite(pinR, r);
analogWrite(pinG, g);
analogWrite(pinB, b);
}
void loop() {
// put your main code here, to run repeatedly:
potValue = analogRead(potPin);
potValue = map(potValue, 0, 1023, 0, 255); //read pot --> map to values from 0 - 255
int reading = digitalRead(buttonPin);
if (reading != lastButtonState) {
lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > debounceDelay) {
if (reading != buttonState) {
buttonState = reading;
if (buttonState == HIGH) {
setting++;
}
}
}
lastButtonState = reading;
if(setting > 3){ // 0=R 1=G 2=B 3=Brightness
setting = 0; // cant get 4 cause there is no 4
}
if(setting == 0){
brightR = potValue;
if(blinking){
RGBset(brightR, brightG, brightB);
}else{
RGBset(brightR, 0, 0);
}
}
if(setting == 1){
brightG = potValue;
if(blinking){
RGBset(brightR, brightG, brightB);
}else{
RGBset(0, brightG, 0);
}
}
if(setting == 2){
brightB = potValue;
if(blinking){
RGBset(brightR, brightG, brightB);
}else{
RGBset(0, 0, brightB);
}
}
if(setting == 3){
brightness = potValue;
brightness = map(brightness, 0, 255, 1, 100); //mapping brightness to values from 1 - 100
R = brightR * brightness / 100; //set value * brightness / 100
G = brightG * brightness / 100; //that leads to get % of set value
B = brightB * brightness / 100; //255 * 50 / 100 = 127,5 ==> 128
RGBset(R, G, B); //it wont blink in thiss setting
}
if(setting != 3){
blinky++;
if(blinky > 1000){
blinking = !blinking;
blinky = 0;
}
}
String output = (String(brightR) + " " + String(R) + " " + String(brightG) + " " + String(G) + " " + String(brightB) + " " + String(B) + " " + String(brightness) + " " + String(potValue) + " " + String(blinking));
Serial.println(output);
delay(1);
}
First, in setup:
pinMode(buttonPin , INPUT);
Second, what are you expected when setting==3? You aren't reloading/updating the variables for brightR brightG brightB. So, when you change setting, you will lost the change of brightness

1820 Dallas Temperture sensor, incorrect value returned

When I run a piece of code that only gathers values from the temp sensor it returns the correct values.
when I integrate this functionality into a larger piece of code it constantly returns -127 degrees.
#include <OneWire.h>
#include <DallasTemperature.h>
#include <SPP.h>
#include <LiquidCrystal.h>
#define ONE_WIRE_BUS 9
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature TempSensor(&oneWire);
USB Usb; // create usb
BTD Btd(&Usb); // create bluetooth dongle instance
SPP SerialBT(&Btd, "Arduino", "0000"); // set device name and pin
LiquidCrystal lcd(7, 6, 5, 4, 3, 2); // create lcd instance using declared pins
int LightPin = A0; // pin connected to light sensor
int LcdType = 0; // variable for lcd display
int state; // variable for storing incoming data
int LDRvalue = 0; // value from light sensor
int totalLdr = 0;
int totalLdrNums = 0;
String output = ""; // output string for light sensor
String output2 = ""; // output string for temp sensor
int tempvalue = 0; // value from temp sensor
int totalTemp = 0;
int totalTempNums = 0;
float celsius = 0; // temp in celsius
void setup() {
Serial.begin(9600); // Begin serial comms at speed 9600
if (Usb.Init() == -1) { // if usb hasn't been initilsed
while(1); //wait
}
lcd.begin(16, 2); // set up lcd with 16 coloums and 2 rows
pinMode(LightPin, INPUT); // declare light pin as input
printStart(); // run printStart method
LcdType = 1; // set lcd display type to 1
TempSensor.begin();
}
void loop() {
Usb.Task(); // polls connected devices for status
if(SerialBT.connected) { // if BT connected
if(SerialBT.available() > 0){ // and BT is available
state = SerialBT.read() - '0'; // read incoming value and turn into regular int (0 - 9 in ascii is 48 - 57)
if(state == 0){ // if value read is zero
checkLightValue(); // run checkLightValue method
SerialBT.write(output[0]); // send first value in string
delay(50); // delay before sending next value
SerialBT.write(output[1]); // send second value
delay(50); // delay before sending next value
SerialBT.write(output[2]); // send third value
}
if(state == 1){ // if value read is 1
checkTempValue();
SerialBT.write(output2[0]); // send first value
delay(50); // delay before sending next value
SerialBT.write(output2[1]); // send second value
delay(50); // delay before sending next value
SerialBT.write(output2[3]); // send third value
delay(50); // delay before sending next value
SerialBT.write(output2[5]); // send fourth value
delay(50); // delay before sending next value
}
if(state == 2){
//Restart();
SerialBT.disconnect();
}
if(state == 3){
LcdType = 1;
}
if(state == 4){
LcdType = 2;
}
if(state == 5){
LcdType = 3;
}
if(LcdType == 1){ // if lcd type variable = 1
printLcd();} // run printLcd method
if (LcdType == 2){
printLcd2();
}
if(LcdType == 3){
printLcd3();
}
}
}
}
//void (*resetFunc)(void) = 0;
void checkLightValue(){
output = ""; // reset output string to nothing
LDRvalue = analogRead(LightPin); // read in light value
totalLdr = totalLdr + LDRvalue;
totalLdrNums = totalLdrNums + 1;
int LDR1 = LDRvalue / 100; // get int 1 from value
int twod = LDRvalue - (LDR1 * 100); // get int 2 and 3 from value
int LDR2 = twod / 10; // get int 2 from value
int LDR3 = twod - (LDR2 * 10); // get int 3 from value
output += LDR1; //
output += LDR2; //
output += LDR3; // appends values to string
}
void checkTempValue(){
output2 = ""; // reset output string to nothing
TempSensor.requestTemperatures();
Serial.println(TempSensor.getTempCByIndex(0));
celsius = TempSensor.getTempCByIndex(0);
totalTemp = totalTemp + celsius;
totalTempNums = totalTempNums + 1;
int c1 = celsius / 100; // get first int from value
int twod = celsius - (c1 * 100); //
int c2 = twod / 10;
int c3 = twod - (c2 *10);
output2 += c1; //
output2 += c2; //
output2 += c3; // add values to string to send
}
void printLcd(){
lcd.clear(); // clear lcd
lcd.print("LDR : "); lcd.print(LDRvalue); // display current ldr value
lcd.setCursor(0,1); // set cursor to second row
lcd.print("Temp : "); lcd.print(celsius); // display current temp value on row 2
}
void printLcd2(){
int Averagevalue = totalLdr / totalLdrNums;
lcd.clear();
lcd.print("Average light :");
lcd.setCursor(0,1);
lcd.print(Averagevalue);
}
void printLcd3(){
int Averagevalue = totalTemp / totalTempNums;
lcd.clear();
lcd.print("Average temp :");
lcd.setCursor(0,1);
lcd.print(Averagevalue);
}
void printStart(){
lcd.clear(); // clear lcd
lcd.setCursor(1,1); // set cursor on second row
lcd.print("Waiting for a Connection ?"); // print message
for(int x=1; x<16; x++) { // do following 15 times
lcd.setCursor(x,0); // set cursor to first row
lcd.print("Arduino Started"); // print message // doing this as lcd scrolls means the top line (message) appears static while the bottom line (message) scrolls
lcd.scrollDisplayLeft(); // scroll display left
delay(250); // delay before moving again
}
}

Resources