arduino accelerometer with servo motor - arduino

I'm currently working on project to operate three motors while sending accelerometer value to computer via bluetooth module. I want the motor operation and value transmission to work seperatly. But when motors operate, the transmission stops. I used the ArduinoThread library, but since I don't understand all the usage, it still has some kind of delay.
Plus, I want two of the motors work first(just once) and the other works after specific time(also just once). But the first setup of two motors and the latter doesn't work.
Please check my code and give me some advice. Thank you!
#include <Wire.h>
#include <SoftwareSerial.h>
#include <Servo.h>
#include <Thread.h>
const int MPU_addr=0x68; // MPU-6050 I2C address
int16_t AcX,AcY,AcZ,GyX,GyY,GyZ;
SoftwareSerial BTSerial(3,2); // TX,RX
Servo servoMini;
Servo servoUp;
Servo servoDown;
int pinMini = 6;
int pinUp = 9;
int pinDown = 10;
int i = 1;
unsigned long tPrev, tNow = 0;
Thread myThread = Thread();
void readAcc(){
Wire.endTransmission(true);
Wire.beginTransmission(MPU_addr);
Wire.write(0x3B); // starting with register 0x3B (ACCEL_XOUT_H)
Wire.endTransmission(false);
Wire.requestFrom(MPU_addr,14,true); // request a total of 14 registers // 14bit??
AcX=Wire.read()<<8|Wire.read(); // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)
//AcY=Wire.read()<<8|Wire.read(); // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
//AcZ=Wire.read()<<8|Wire.read(); // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
//GyX=Wire.read()<<8|Wire.read(); // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L)
//GyY=Wire.read()<<8|Wire.read(); // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L)
//GyZ=Wire.read()<<8|Wire.read(); // 0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L)
BTSerial.println(AcX); // 16bit
Serial.println(AcX);
// delay(25);
}
void setup(){
// I2C
Wire.begin();
Wire.beginTransmission(MPU_addr);
Wire.write(0x6B); // PWR_MGMT_1 register
Wire.write(0); // set to zero (wakes up the MPU-6050)
// serial, bluetooth
Serial.begin(9600);
BTSerial.begin(9600);
Serial.println("CLEARDATA");
Serial.println("ONLY AcX");
// servo
servoMini.attach(pinMini);
servoUp.attach(pinUp);
servoDown.attach(pinDown);
pinMode(pinMini, OUTPUT);
pinMode(pinUp, OUTPUT);
pinMode(pinDown, OUTPUT);
servoMini.write(145);
servoUp.write(180);
servoDown.write(0);
// Thread(MPU-6050)
myThread.onRun(readAcc);
myThread.setInterval(20);
}
void loop(){
while(i == 1){
//delay(1000);
tNow = millis();
myThread.run();
servoUp.attach(pinUp);
servoDown.attach(pinDown);
servoUp.write(60);
servoDown.write(120);
if((tNow - tPrev)>= 1000){
servoMini.attach(pinMini);
servoMini.write(180);
i++;
}
}
servoMini.detach();
myThread.run();
}

I think you probably need something like this?
#include <Wire.h>
#include <SoftwareSerial.h>
#include <Servo.h>
#include <Thread.h>
const int MPU_addr = 0x68; // MPU-6050 I2C address
int16_t AcX, AcY, AcZ, GyX, GyY, GyZ;
SoftwareSerial BTSerial(3, 2); // TX,RX
Servo servoMini;
Servo servoUp;
Servo servoDown;
int pinMini = 6;
int pinUp = 9;
int pinDown = 10;
int i = 1;
unsigned long tPrev, tNow = 0;
Thread accelleroThread = Thread();
Thread servoThread = Thread();
void main() {
setup();
// Thread(MPU-6050)
accelleroThread.onRun(readAcc);
accelleroThread.setInterval(20);
// Thread(MPU-6050)
servoThread.onRun(controlServo);
servoThread.setInterval(20);
accelleroThread.run();
servoThread.run();
}
void setup() {
// I2C
Wire.begin();
Wire.beginTransmission(MPU_addr);
Wire.write(0x6B); // PWR_MGMT_1 register
Wire.write(0); // set to zero (wakes up the MPU-6050)
// serial, bluetooth
Serial.begin(9600);
BTSerial.begin(9600);
Serial.println("CLEARDATA");
Serial.println("ONLY AcX");
// servo
servoMini.attach(pinMini);
servoUp.attach(pinUp);
servoDown.attach(pinDown);
pinMode(pinMini, OUTPUT);
pinMode(pinUp, OUTPUT);
pinMode(pinDown, OUTPUT);
servoMini.write(145);
servoUp.write(180);
servoDown.write(0);
}
void readAcc() {
while (1) {
Wire.endTransmission(true);
Wire.beginTransmission(MPU_addr);
Wire.write(0x3B); // starting with register 0x3B (ACCEL_XOUT_H)
Wire.endTransmission(false);
Wire.requestFrom(MPU_addr, 14, true); // request a total of 14 registers // 14bit??
AcX = Wire.read() << 8 | Wire.read(); // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)
//AcY=Wire.read()<<8|Wire.read(); // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
//AcZ=Wire.read()<<8|Wire.read(); // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
//GyX=Wire.read()<<8|Wire.read(); // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L)
//GyY=Wire.read()<<8|Wire.read(); // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L)
//GyZ=Wire.read()<<8|Wire.read(); // 0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L)
BTSerial.println(AcX); // 16bit
Serial.println(AcX);
// delay(25);
}
}
void controlServo() {
while (1) {
//delay(1000);
tNow = millis();
myThread.run();
servoUp.attach(pinUp);
servoDown.attach(pinDown);
servoUp.write(60);
servoDown.write(120);
if ((tNow - tPrev) >= 1000) {
servoMini.attach(pinMini);
servoMini.write(180);
i++;
}
}
servoMini.detach();
}
Note I just moved some blocks around to get 2 threads running (1 controlling the servo, 1 reading the accellero).

Related

(.text+0x0): multiple definition of `__vector_13'

Using NewPing.h seems to be the main issue.
Code:
#include <LedControl.h>
#include "pitches.h"
#include "SR04.h"
#include "NewPing.h"
#define TRIGGER_PIN 13
#define ECHO_PIN 8
#define MAX_DISTANCE 200
NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE);
long duration;
int distance;
int DIN = 12;
int CS = 11;
int CLK = 10;
LedControl lc=LedControl(DIN,CLK,CS,0);
const int buzzer = 9;
void setup(){
lc.shutdown(0,false); //The MAX72XX is in power-saving mode on startup
lc.setIntensity(0,15); // Set the brightness to maximum value
lc.clearDisplay(0); // and clear the display
pinMode(buzzer, OUTPUT); //buzzer shit
pinMode(TRIGGER_PIN, OUTPUT); // Sets the trigPin as an OUTPUT
pinMode(ECHO_PIN, INPUT); // Sets the echoPin as an INPUT
Serial.begin(9600); // // Serial Communication is starting with 9600 of baudrate speed
}
void loop(){
unsigned int uS = sonar.ping();
Serial.print(uS / US_ROUNDTRIP_CM);
byte a[8]= {0x18,0x18,0x18,0x18,0x18,0x00,0x18,0x18,};
byte b[8]= {0x18,0x18,0x18,0x18,0x00,0x18,0x18,0x00,};
byte c[8]= {0x18,0x18,0x18,0x18,0x18,0x00,0x18,0x18,}; //done
byte d[8] = {0x00,0x18,0x18,0x18,0x18,0x18,0x00,0x18,}; //done
byte e[8]= {0x18,0x5a,0x3c,0x18,0x18,0x24,0x5a,0x18,}; //done
byte f[8]= {0x99,0x5a,0x18,0x18,0x18,0x00,0x5a,0x99,}; //done
byte g[8]= {0x99,0x18,0x18,0x18,0x18,0x00,0x18,0x99,};
byte h[8]= {0x18,0x18,0x18,0x18,0x18,0x00,0x18,0x18,};
if (uS <= 20){
printByte(a);
tone(buzzer, 1000);
delay(100);
printByte(b);
noTone(buzzer);
delay(100);
printByte(c);
tone(buzzer, 1000);
delay(100);
printByte(d);
noTone(buzzer);
delay(100);
printByte(e);
tone(buzzer, 1000);
delay (100);
printByte(f);
noTone(buzzer);
delay (100);
printByte(g);
tone(buzzer, 1000);
delay (100);
printByte(h);
noTone(buzzer);
delay(1000);
}
}
void printByte(byte character [])
{
int i = 0;
for(i=0;i<8;i++)
{
lc.setRow(0,i,character[i]);
}
}
The main thing that stands out in the error is the line
"(.text+0x0): multiple definition of `__vector_13'
C:\Users\name\AppData\Local\Temp\arduino_build_789753\libraries\NewPing\NewPing.cpp.o (symbol from plugin):(.text+0x0): first defined here".
However, I don't exactly know how to solve it.

How to publish and subscribe to MQTT broker through GSM Module in Arduino/ESP8266?

I am currently working in a project where I have to publish and possibly subscribe to MQTT topic over GSM network (I am using ESP8266 and Ai Thinker A6 GSM Module). So far I am able to publish message to the broker once using MQTT Example code from TinyGSM library,where they pass the GPRS client instance to Pubsub Client class, but when I add a code in loop to publish message continuously every n seconds. The message is published only once or twice and then freezes.
I doubt the mqttclient.loop() function in the void loop(). But, I am just wondering is there any other library which is completely tested, because the TinyGSM developer itself has mentioned this code is not tested in github.
The example code with mqtt publish in loop
// Select your modem:
#define TINY_GSM_MODEM_SIM800
// #define TINY_GSM_MODEM_SIM808
// #define TINY_GSM_MODEM_SIM868
// #define TINY_GSM_MODEM_SIM900
// #define TINY_GSM_MODEM_SIM7000
// #define TINY_GSM_MODEM_SIM5360
// #define TINY_GSM_MODEM_SIM7600
// #define TINY_GSM_MODEM_UBLOX
// #define TINY_GSM_MODEM_SARAR4
// #define TINY_GSM_MODEM_M95
// #define TINY_GSM_MODEM_BG96
// #define TINY_GSM_MODEM_A6
// #define TINY_GSM_MODEM_A7
// #define TINY_GSM_MODEM_M590
// #define TINY_GSM_MODEM_MC60
// #define TINY_GSM_MODEM_MC60E
// #define TINY_GSM_MODEM_ESP8266
// #define TINY_GSM_MODEM_XBEE
// #define TINY_GSM_MODEM_SEQUANS_MONARCH
// Set serial for debug console (to the Serial Monitor, default speed 115200)
#define SerialMon Serial
// Set serial for AT commands (to the module)
// Use Hardware Serial on Mega, Leonardo, Micro
#define SerialAT Serial1
// or Software Serial on Uno, Nano
//#include <SoftwareSerial.h>
//SoftwareSerial SerialAT(2, 3); // RX, TX
// See all AT commands, if wanted
// #define DUMP_AT_COMMANDS
// Define the serial console for debug prints, if needed
#define TINY_GSM_DEBUG SerialMon
// Range to attempt to autobaud
#define GSM_AUTOBAUD_MIN 9600
#define GSM_AUTOBAUD_MAX 115200
// Add a reception delay - may be needed for a fast processor at a slow baud rate
// #define TINY_GSM_YIELD() { delay(2); }
// Define how you're planning to connect to the internet
#define TINY_GSM_USE_GPRS true
#define TINY_GSM_USE_WIFI false
// set GSM PIN, if any
#define GSM_PIN ""
// Your GPRS credentials, if any
const char apn[] = "YourAPN";
const char gprsUser[] = "";
const char gprsPass[] = "";
// Your WiFi connection credentials, if applicable
const char wifiSSID[] = "YourSSID";
const char wifiPass[] = "YourWiFiPass";
// MQTT details
const char* broker = "broker.hivemq.com";
const char* topicLed = "GsmClientTest/led";
const char* topicInit = "GsmClientTest/init";
const char* topicLedStatus = "GsmClientTest/ledStatus";
#include <TinyGsmClient.h>
#include <PubSubClient.h>
// Just in case someone defined the wrong thing..
#if TINY_GSM_USE_GPRS && not defined TINY_GSM_MODEM_HAS_GPRS
#undef TINY_GSM_USE_GPRS
#undef TINY_GSM_USE_WIFI
#define TINY_GSM_USE_GPRS false
#define TINY_GSM_USE_WIFI true
#endif
#if TINY_GSM_USE_WIFI && not defined TINY_GSM_MODEM_HAS_WIFI
#undef TINY_GSM_USE_GPRS
#undef TINY_GSM_USE_WIFI
#define TINY_GSM_USE_GPRS true
#define TINY_GSM_USE_WIFI false
#endif
#ifdef DUMP_AT_COMMANDS
#include <StreamDebugger.h>
StreamDebugger debugger(SerialAT, SerialMon);
TinyGsm modem(debugger);
#else
TinyGsm modem(SerialAT);
#endif
TinyGsmClient client(modem);
PubSubClient mqtt(client);
#define LED_PIN 13
int ledStatus = LOW;
uint32_t lastReconnectAttempt = 0;
void mqttCallback(char* topic, byte* payload, unsigned int len) {
SerialMon.print("Message arrived [");
SerialMon.print(topic);
SerialMon.print("]: ");
SerialMon.write(payload, len);
SerialMon.println();
// Only proceed if incoming message's topic matches
if (String(topic) == topicLed) {
ledStatus = !ledStatus;
digitalWrite(LED_PIN, ledStatus);
mqtt.publish(topicLedStatus, ledStatus ? "1" : "0");
}
}
boolean mqttConnect() {
SerialMon.print("Connecting to ");
SerialMon.print(broker);
// Connect to MQTT Broker
boolean status = mqtt.connect("GsmClientTest");
// Or, if you want to authenticate MQTT:
//boolean status = mqtt.connect("GsmClientName", "mqtt_user", "mqtt_pass");
if (status == false) {
SerialMon.println(" fail");
return false;
}
SerialMon.println(" success");
mqtt.publish(topicInit, "GsmClientTest started");
mqtt.subscribe(topicLed);
return mqtt.connected();
}
void setup() {
// Set console baud rate
SerialMon.begin(115200);
delay(10);
pinMode(LED_PIN, OUTPUT);
// !!!!!!!!!!!
// Set your reset, enable, power pins here
// !!!!!!!!!!!
SerialMon.println("Wait...");
// Set GSM module baud rate
// TinyGsmAutoBaud(SerialAT,GSM_AUTOBAUD_MIN,GSM_AUTOBAUD_MAX);
SerialAT.begin(9600);
delay(3000);
// Restart takes quite some time
// To skip it, call init() instead of restart()
SerialMon.println("Initializing modem...");
modem.restart();
// modem.init();
String modemInfo = modem.getModemInfo();
SerialMon.print("Modem Info: ");
SerialMon.println(modemInfo);
#if TINY_GSM_USE_GPRS
// Unlock your SIM card with a PIN if needed
if ( GSM_PIN && modem.getSimStatus() != 3 ) {
modem.simUnlock(GSM_PIN);
}
#endif
#if TINY_GSM_USE_WIFI
// Wifi connection parameters must be set before waiting for the network
SerialMon.print(F("Setting SSID/password..."));
if (!modem.networkConnect(wifiSSID, wifiPass)) {
SerialMon.println(" fail");
delay(10000);
return;
}
SerialMon.println(" success");
#endif
#if TINY_GSM_USE_GPRS && defined TINY_GSM_MODEM_XBEE
// The XBee must run the gprsConnect function BEFORE waiting for network!
modem.gprsConnect(apn, gprsUser, gprsPass);
#endif
SerialMon.print("Waiting for network...");
if (!modem.waitForNetwork()) {
SerialMon.println(" fail");
delay(10000);
return;
}
SerialMon.println(" success");
if (modem.isNetworkConnected()) {
SerialMon.println("Network connected");
}
#if TINY_GSM_USE_GPRS
// GPRS connection parameters are usually set after network registration
SerialMon.print(F("Connecting to "));
SerialMon.print(apn);
if (!modem.gprsConnect(apn, gprsUser, gprsPass)) {
SerialMon.println(" fail");
delay(10000);
return;
}
SerialMon.println(" success");
if (modem.isGprsConnected()) {
SerialMon.println("GPRS connected");
}
#endif
// MQTT Broker setup
mqtt.setServer(broker, 1883);
mqtt.setCallback(mqttCallback);
}
void loop() {
if (!mqtt.connected()) {
SerialMon.println("=== MQTT NOT CONNECTED ===");
// Reconnect every 10 seconds
uint32_t t = millis();
if (t - lastReconnectAttempt > 10000L) {
lastReconnectAttempt = t;
if (mqttConnect()) {
lastReconnectAttempt = 0;
}
}
delay(100);
return;
}
else
{
mqtt.publish("Topic/test","Hi");
delay(1000);
}
mqtt.loop();
}

Arduino Photoresistor

I'm trying to make an Arduino project where I need the value of light to determine when a song play's on the mp3 module. I'm trying to loop through the value's of being sent to the photoresistor, but I'm only receiving 1 number, how can I get a continuous loop of values/data?
#include "Arduino.h"
#include "SoftwareSerial.h"
#include "DFRobotDFPlayerMini.h"
SoftwareSerial mySoftwareSerial(10, 11); // RX, TX
DFRobotDFPlayerMini myDFPlayer;
void printDetail(uint8_t type, int value);
void photoLoop() {
Serial.begin(2400);
pinMode(lrdPin, INPUT);
int ldrStatus = analogRead(ldrPin);
Serial.println(ldrStatus);
}
void setup() {
mySoftwareSerial.begin(9600);
Serial.begin(115200);
Serial.println();
Serial.println(F("DFRobot DFPlayer Mini Demo"));
Serial.println(F("Initializing DFPlayer ... (May take 3~5 seconds)"));
if (!myDFPlayer.begin(mySoftwareSerial)) { //Use softwareSerial to communicate with mp3.
Serial.println(F("Unable to begin:"));
Serial.println(F("1.Please recheck the connection!"));
Serial.println(F("2.Please insert the SD card!"));
while (true);
} else {
photoLoop();
}
myDFPlayer.volume(30); //Set volume value. From 0 to 30
myDFPlayer.play(3); //Play the first mp3
}
void loop() {
while (!Serial.available()); //wait until a byte was received
analogWrite(9, Serial.read());//output received byte
static unsigned long timer = millis();
if (millis() - timer > 3000) {
timer = millis();
//myDFPlayer.next(); //Play next mp3 every 3 second.
}
// if (myDFPlayer.available()) {
// printDetail(myDFPlayer.readType(), myDFPlayer.read()); //Print the detail message from DFPlayer to handle different errors and states.
// }
}
you are not reading the value from photo resistor in loop function.
you only read the value once
int ldrStatus = analogRead(ldrPin);
That too in setup. so you are only receiving one number.
Why did you use two Serial.begin() statements - 115200 and 2400 ?
Try this
#include "Arduino.h"
#include "SoftwareSerial.h"
#include "DFRobotDFPlayerMini.h"
SoftwareSerial mySoftwareSerial(10, 11); // RX, TX
DFRobotDFPlayerMini myDFPlayer;
void printDetail(uint8_t type, int value);
void photoLoop() {
// Serial.begin(2400); // YOU DONT NEED THIS
pinMode(lrdPin, INPUT);
int ldrStatus = analogRead(ldrPin);
Serial.println(ldrStatus);
}
void setup() {
mySoftwareSerial.begin(9600);
Serial.begin(115200);
Serial.println();
Serial.println(F("DFRobot DFPlayer Mini Demo"));
Serial.println(F("Initializing DFPlayer ... (May take 3~5 seconds)"));
if (!myDFPlayer.begin(mySoftwareSerial)) { //Use softwareSerial to communicate with mp3.
Serial.println(F("Unable to begin:"));
Serial.println(F("1.Please recheck the connection!"));
Serial.println(F("2.Please insert the SD card!"));
while (true);
}
else {
photoLoop();
}
myDFPlayer.volume(30); //Set volume value. From 0 to 30
myDFPlayer.play(3); //Play the first mp3
}
void loop() {
//CALL photoLoop in LOOP
photoLoop()
while (!Serial.available()); //wait until a byte was received
analogWrite(9, Serial.read());//output received byte
static unsigned long timer = millis();
if (millis() - timer > 3000) {
timer = millis();
//myDFPlayer.next(); //Play next mp3 every 3 second.
}
// if (myDFPlayer.available()) {
// printDetail(myDFPlayer.readType(), myDFPlayer.read()); //Print the detail message from DFPlayer to handle different errors and states.
// }
}

Define Pin RX, TX Without SoftwareSerial Arduino

Hi I did 2 diferent codes, then after verifying that they work i try to combine them and I got a problem. I used GSM.h to controle my GSM module, and to controle the GPS I used the SoftwareSerial.h.
I tryed to combine these to codes and this 2 libraries conflit with each other.
Can some one help me?
This is my code
//GSM
#include <GSM.h>
#define PINNUMBER "3805"
GSM gsmAccess; // include a 'true' parameter for debug enabled
GSM_SMS sms;
//N de telefone de envio
char remoteNumber[20]= "914181875";
//Conteudo do SMS
char txtMsg[200]="Tester";
int val = 0;
//GPS
//#include <SoftwareSerial.h>
#include <TinyGPS.h>
TinyGPS gps;
SoftwareSerial ss(4, 3);
static void print_float(float val, float invalid, int len, int prec);
int button = 7;
void setup()
{
// initialize serial communications
pinMode(button, INPUT);
Serial.begin(9600);
Serial.println("SMS Messages Sender");
// connection state
boolean notConnected = true;
// Start GSM shield
// If your SIM has PIN, pass it as a parameter of begin() in quotes
while(notConnected)
{
if(gsmAccess.begin(PINNUMBER)==GSM_READY)
notConnected = false;
else
{
Serial.println("Not connected");
delay(1000);
}
}
Serial.println("GSM initialized");
}
void loop()
{
val = digitalRead(button);
if (val == HIGH){
sendSMS();
}
}
void sendSMS(){
Serial.print("Message to mobile number: ");
Serial.println(remoteNumber);
// sms text
Serial.println("SENDING");
Serial.println();
Serial.println("Message:");
Serial.println(txtMsg);
// send the message
sms.beginSMS(remoteNumber);
sms.print(txtMsg);
sms.endSMS();
Serial.println("\nCOMPLETE!\n");
}
I would try using the AltSoftSerial library instead of SoftwareSerial:
https://github.com/PaulStoffregen/AltSoftSerial
The disadvantage of this library is it requires you to use specific pins for serial communication with your GPS hardware, which are different from the pins you're currently using:
// AltSoftSerial always uses these pins:
//
// Board Transmit Receive PWM Unusable
// ----- -------- ------- ------------
// Teensy 3.0 & 3.1 21 20 22
// Teensy 2.0 9 10 (none)
// Teensy++ 2.0 25 4 26, 27
// Arduino Uno 9 8 10
// Arduino Leonardo 5 13 (none)
// Arduino Mega 46 48 44, 45
// Wiring-S 5 6 4
// Sanguino 13 14 12
I don't have the hardware to test but the following code does compile:
//GSM
#include <GSM.h>
#define PINNUMBER "3805"
GSM gsmAccess; // include a 'true' parameter for debug enabled
GSM_SMS sms;
//N de telefone de envio
char remoteNumber[20]= "914181875";
//Conteudo do SMS
char txtMsg[200]="Tester";
int val = 0;
//GPS
#include <AltSoftSerial.h>
AltSoftSerial ss;
#include <TinyGPS.h>
TinyGPS gps;
static void print_float(float val, float invalid, int len, int prec);
int button = 7;
void setup()
{
// initialize serial communications
pinMode(button, INPUT);
Serial.begin(9600);
Serial.println("SMS Messages Sender");
// connection state
boolean notConnected = true;
// Start GSM shield
// If your SIM has PIN, pass it as a parameter of begin() in quotes
while(notConnected)
{
if(gsmAccess.begin(PINNUMBER)==GSM_READY)
notConnected = false;
else
{
Serial.println("Not connected");
delay(1000);
}
}
Serial.println("GSM initialized");
}
void loop()
{
val = digitalRead(button);
if (val == HIGH){
sendSMS();
}
}
void sendSMS(){
Serial.print("Message to mobile number: ");
Serial.println(remoteNumber);
// sms text
Serial.println("SENDING");
Serial.println();
Serial.println("Message:");
Serial.println(txtMsg);
// send the message
sms.beginSMS(remoteNumber);
sms.print(txtMsg);
sms.endSMS();
Serial.println("\nCOMPLETE!\n");
}

Fixing FIFO Overflow on Arduino

I'm multiplexing 3 IMU-6050 using a MUX4051. This is the original code:
#include "Wire.h"
const int MPU=0x68; // I2C address of the MPU-6050
int16_t AcX,AcY,AcZ,Tmp,GyX,GyY,GyZ;
int Acc_ctrl_1 = 9;
int Acc_ctrl_2 = 10;
int Acc_ctrl_3 = 11;
int chip_enable1 = 5;
void setup() {
Wire.begin(); // wake up I2C bus
// set I/O pins to outputs
Wire.beginTransmission(MPU);
Wire.write(0x6B); // PWR_MGMT_1 register
Wire.write(0); // set to zero (wakes up the MPU-6050)
Wire.endTransmission(true);
Serial.begin(115200);
pinMode(Acc_ctrl_1, OUTPUT); //S0
pinMode(Acc_ctrl_2, OUTPUT); //S1
pinMode(Acc_ctrl_3, OUTPUT); //S2 address lines
pinMode(chip_enable1, OUTPUT);
//S0=1, S1=2 and S2=4 so Y0= S0=0,S1=0,S2=0, Y4=S0=0,S1=0,S2=1
}
void loop() {
//Enable the MUX Chip 1 - Active Low
digitalWrite(chip_enable1, LOW);
// control signal for First Accelerometer
Serial.println("IMU 1");
digitalWrite(Acc_ctrl_1, LOW);
digitalWrite(Acc_ctrl_2, LOW);
digitalWrite(Acc_ctrl_3, LOW);
readAccele();
delay(500);
// control signal for SECOND Accelerometer
Serial.println("IMU 2");
digitalWrite(Acc_ctrl_1, HIGH);
digitalWrite(Acc_ctrl_2, LOW);
digitalWrite(Acc_ctrl_3, LOW);
readAccele();
delay(500);
// control signal for THIRD Accelerometer
Serial.println("IMU 3");
digitalWrite(Acc_ctrl_1, LOW);
digitalWrite(Acc_ctrl_2, HIGH);
digitalWrite(Acc_ctrl_3, LOW);
readAccele();
delay(500);
}
void readAccele()
{
Wire.beginTransmission(MPU);// I2C address code thanks to John Boxall
Wire.write(0x3B); // starting with register 0x3B (ACCEL_XOUT_H)
Wire.endTransmission(false);
Wire.requestFrom(MPU,14,true); // request a total of 14 registers
AcX=Wire.read()<<8|Wire.read(); // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)
AcY=Wire.read()<<8|Wire.read(); // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
AcZ=Wire.read()<<8|Wire.read(); // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
Tmp=Wire.read()<<8|Wire.read(); // 0x41 (TEMP_OUT_H) & 0x42 (TEMP_OUT_L)
GyX=Wire.read()<<8|Wire.read(); // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L)
GyY=Wire.read()<<8|Wire.read(); // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L)
GyZ=Wire.read()<<8|Wire.read(); // 0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L)
Serial.print("AcX = "); Serial.print(AcX);
Serial.print(" | AcY = "); Serial.print(AcY);
Serial.print(" | AcZ = "); Serial.print(AcZ);
Serial.print(" | Tmp = "); Serial.print(Tmp/340.00+36.53); //equation for temperature in degrees C from datasheet
Serial.print(" | GyX = "); Serial.print(GyX);
Serial.print(" | GyY = "); Serial.print(GyY);
Serial.print(" | GyZ = "); Serial.println(GyZ);
delay(5);
}
I implemented it into the Jeff Rowberg example code:
// I2C device class (I2Cdev) demonstration Arduino sketch for MPU6050 class using DMP (MotionApps v2.0)
// 6/21/2012 by Jeff Rowberg <jeff#rowberg.net>
uint8_t devStatus; // return status after each device operation (0 = success, !0 = error)
uint8_t mpuIntStatus; // holds actual interrupt status byte from MPU
bool dmpReady = false; // set true if DMP init was successful
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];
// I2Cdev and MPU6050 must be installed as libraries, or else the .cpp/.h files
// for both classes must be in the include path of your project
#include "I2Cdev.h"
#include "MPU6050_6Axis_MotionApps20.h"
//#include "MPU6050.h" // not necessary if using MotionApps include file
// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation
// is used in I2Cdev.h
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
#include "Wire.h"
#endif
// class default I2C address is 0x68
// specific I2C addresses may be passed as a parameter here
// AD0 low = 0x68 (default for SparkFun breakout and InvenSense evaluation board)
MPU6050 mpu;
// uncomment "OUTPUT_READABLE_QUATERNION" if you want to see the actual
// quaternion components in a [w, x, y, z] format (not best for parsing
// on a remote host such as Processing or something though)
//#define OUTPUT_READABLE_QUATERNION
// uncomment "OUTPUT_READABLE_EULER" if you want to see Euler angles
// (in degrees) calculated from the quaternions coming from the FIFO.
// Note that Euler angles suffer from gimbal lock (for more info, see
// http://en.wikipedia.org/wiki/Gimbal_lock)
#define OUTPUT_READABLE_EULER
// uncomment "OUTPUT_READABLE_WORLDACCEL" if you want to see acceleration
// components with gravity removed and adjusted for the world frame of
// reference (yaw is relative to initial orientation, since no magnetometer
// is present in this case). Could be quite handy in some cases.
#define OUTPUT_READABLE_WORLDACCEL
int Acc_ctrl_1 = 9;
int Acc_ctrl_2 = 10;
int Acc_ctrl_3 = 11;
int chip_enable1 = 5;
int chip_enable2 = 6;
#define LED_PIN 13 // (Arduino is 13, Teensy is 11, Teensy++ is 6)
bool blinkState = false;
// MPU control/status vars
//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
// packet structure for InvenSense teapot demo
uint8_t teapotPacket[14] = { '$', 0x02, 0,0, 0,0, 0,0, 0,0, 0x00, 0x00, '\r', '\n' };
// ================================================================
// === INTERRUPT DETECTION ROUTINE ===
// ================================================================
volatile bool mpuInterrupt = false; // indicates whether MPU interrupt pin has gone high
void dmpDataReady() {
mpuInterrupt = true;
}
// ================================================================
// === INITIAL SETUP ===
// ================================================================
void setup() {
pinMode(Acc_ctrl_1, OUTPUT); //S0
pinMode(Acc_ctrl_2, OUTPUT); //S1
pinMode(Acc_ctrl_3, OUTPUT); //S2 address lines
pinMode(chip_enable1, OUTPUT);
// join I2C bus (I2Cdev library doesn't do this automatically)
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
Wire.begin();
TWBR = 24; // 400kHz I2C clock (200kHz if CPU is 8MHz)
#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
Fastwire::setup(400, true);
#endif
// initialize serial communication
// (115200 chosen because it is required for Teapot Demo output, but it's
// really up to you depending on your project)
Serial.begin(115200);
while (!Serial); // wait for Leonardo enumeration, others continue immediately
// initialize device
Serial.println(F("Initializing I2C devices..."));
mpu.initialize();
// verify connection
Serial.println(F("Testing device connections..."));
Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed"));
// wait for ready
Serial.println(F("\nSend any character to begin DMP programming and demo: "));
while (Serial.available() && Serial.read()); // empty buffer
while (!Serial.available()); // wait for data
while (Serial.available() && Serial.read()); // empty buffer again
// load and configure the DMP
Serial.println(F("Initializing DMP..."));
devStatus = mpu.dmpInitialize();
// supply your own gyro offsets here, scaled for min sensitivity
mpu.setXGyroOffset(220);
mpu.setYGyroOffset(76);
mpu.setZGyroOffset(-85);
mpu.setZAccelOffset(1788); // 1688 factory default for my test chip
// make sure it worked (returns 0 if so)
if (devStatus == 0) {
// turn on the DMP, now that it's ready
Serial.println(F("Enabling DMP..."));
mpu.setDMPEnabled(true);
// enable Arduino interrupt detection
Serial.println(F("Enabling interrupt detection (Arduino external interrupt 0)..."));
attachInterrupt(0, dmpDataReady, RISING);
mpuIntStatus = mpu.getIntStatus();
// set our DMP Ready flag so the main loop() function knows it's okay to use it
Serial.println(F("DMP ready! Waiting for first interrupt..."));
dmpReady = true;
// get expected DMP packet size for later comparison
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(")"));
}
// configure LED for output
pinMode(LED_PIN, OUTPUT);
}
// ================================================================
// === MAIN PROGRAM LOOP ===
// ================================================================
void loop() {
//Enable the MUX Chip 1 - Active Low
digitalWrite(chip_enable1, LOW);
// control signal for First Accelerometer
Serial.println("IMU 1");
digitalWrite(Acc_ctrl_1, LOW);
digitalWrite(Acc_ctrl_2, LOW);
digitalWrite(Acc_ctrl_3, LOW);
readAccele();
delay(500);
// control signal for SECOND Accelerometer
Serial.println("IMU 2");
digitalWrite(Acc_ctrl_1, HIGH);
digitalWrite(Acc_ctrl_2, LOW);
digitalWrite(Acc_ctrl_3, LOW);
readAccele();
delay(500);
// control signal for THIRD Accelerometer
Serial.println("IMU 3");
digitalWrite(Acc_ctrl_1, LOW);
digitalWrite(Acc_ctrl_2, HIGH);
digitalWrite(Acc_ctrl_3, LOW);
readAccele();
delay(500);
}
void readAccele(){
// 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) {
// other program behavior stuff here
}
// 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 & 0x10) || fifoCount == 1024) {
// reset so we can continue cleanly
mpu.resetFIFO();
Serial.println(F("FIFO overflow!"));
// otherwise, check for DMP data ready interrupt (this should happen frequently)
} else if (mpuIntStatus & 0x02) {
// 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;
#ifdef OUTPUT_READABLE_QUATERNION
// display quaternion values in easy matrix form: w x y z
mpu.dmpGetQuaternion(&q, fifoBuffer);
Serial.print("quat\t");
Serial.print(q.w);
Serial.print("\t");
Serial.print(q.x);
Serial.print("\t");
Serial.print(q.y);
Serial.print("\t");
Serial.println(q.z);
#endif
#ifdef OUTPUT_READABLE_EULER
// display Euler angles in degrees
mpu.dmpGetQuaternion(&q, fifoBuffer);
mpu.dmpGetEuler(euler, &q);
Serial.print("euler\t");
Serial.print(euler[0] * 180/M_PI);
Serial.print("\t");
Serial.print(euler[1] * 180/M_PI);
Serial.print("\t");
Serial.println(euler[2] * 180/M_PI);
#endif
#ifdef OUTPUT_READABLE_WORLDACCEL
// display initial world-frame acceleration, adjusted to remove gravity
// and rotated based on known orientation from quaternion
mpu.dmpGetQuaternion(&q, fifoBuffer);
mpu.dmpGetAccel(&aa, fifoBuffer);
mpu.dmpGetGravity(&gravity, &q);
mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity);
mpu.dmpGetLinearAccelInWorld(&aaWorld, &aaReal, &q);
Serial.print("aworld\t");
Serial.print(aaWorld.x);
Serial.print("\t");
Serial.print(aaWorld.y);
Serial.print("\t");
Serial.println(aaWorld.z);
#endif
;
}
}
But this is what the serial prints, FIFO Overflow.. I tried to fix it but couldn't. I can't upload an image so Ill copy and paste the serial output here as code...
Send any character to begin DMP programming and demo:
Initializing DMP...
Enabling DMP...
Enabling interrupt detection (Arduino external interrupt 0)...
DMP ready! Waiting for first interrupt...
IMU 1
IMU 2
IMU 3
IMU 1
FIFO overflow!
IMU 2
IMU 3
IMU 1
FIFO overflow!
IMU 2
IMU 3
IMU 1
FIFO overflow!
IMU 2
IMU 3
IMU 1
FIFO overflow!
IMU 2
IMU 3
IMU 1
FIFO overflow!
IMU 2
IMU 3
IMU 1
FIFO overflow!
IMU 2
IMU 3
IMU 1
FIFO overflow!
IMU 2
IMU 3
IMU 1
I have been working on a stable library to get all the useful information using the MPU6050_6Axis_MotionApps20 provided by I2Cdev package. I don't know if it is useful for you, but I upload it for everyone having problems dealing with it:
GYRO.h:
#ifndef GYRO
#define GYRO
#include "Arduino.h"
#include "I2Cdev.h"
#include "MPU6050_6Axis_MotionApps20.h"
#include "Wire.h"
#define INTERRUPT_PIN 2 //24
#define CALIBRATION_LOOPS 500
//Error codes
#define EC_NO_ERROR 0
#define EC_DMP_MEMORY_WRITING_FAILED 1
#define EC_DMP_CONFIG_WRITING_FAILED 2
#define EC_NO_CONNECTION 3
//Offsets, put your own offsets here
#define GYRO_GX_OFFSET 93
#define GYRO_GY_OFFSET 0
#define GYRO_GZ_OFFSET 7
#define GYRO_AX_OFFSET -2550
#define GYRO_AY_OFFSET 1978
#define GYRO_AZ_OFFSET 499
class GYRO{
public:
GYRO(void);
uint8_t begin(void);
void update(void);
//All are made following the arrows with the right hand rule
inline VectorFloat getGyroscope(){return gyroscope; }
//All are made following the arrows
inline VectorDouble getAccelerometer(){return accelerometer; }
//A positive 1, indicates that the gravity is going in the oppsite way of the arrow drawed on the sensor
inline VectorFloat getGravity(){return gravity; }
//Returns the temperature in ºC
inline float getTemperature(){return temperature; }
//The time that has passed for calculating the speed with the acceleration
inline unsigned long getMicrosSpent(){return microsSpent; }
inline bool isGyroscopeUpdated(){return gyroscopeUpdated; }
private:
//Gyroscope
MPU6050 gyro; //Gyroscope configured with pin ADO-LOW
//Gyroscope readings
// MPU control/status vars
uint8_t gyroIntStatus; // 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
VectorFloat gravity; // [x, y, z] gravity vector
float ypr[3]; // [yaw, pitch, roll] yaw/pitch/roll container and gravity vector
VectorFloat gyroscope; // [x, y, z] gyroscope vector
VectorInt16 rawAccelerometer; // [x, y, z] raw acceleromer
VectorDouble accelerometer; // [x, y, z] accelerometer in m/s2
float temperature; // temperature in ºC
unsigned long lastMicros;
unsigned long actualMicros;
unsigned long microsSpent;
bool gyroscopeUpdated;
int loops_before_calibration;
};
#endif
GYRO.cpp:
#include "GYRO.h"
#include "Arduino.h"
#include "MPU6050_6Axis_MotionApps20.h"
#include "Wire.h"
volatile bool interrupt = false;
void dmpDataReady(void) {
interrupt = true;
}
GYRO::GYRO(void){
gyro = MPU6050(0x68); //Change to 0x69 if the AD0 pin of your MPU6050 is HIGH
}
uint8_t GYRO::begin(void){
Wire.begin();
Wire.setClock(400000);
uint8_t errorCode;
//Gyro initialization
gyro.initialize();
pinMode(INTERRUPT_PIN, INPUT);
if(gyro.testConnection()){
Serial.println(F("\nSend any character to begin the calibration and initialization of the gyro: "));
while (Serial.available() && Serial.read());
while (!Serial.available());
while (Serial.available() && Serial.read());
devStatus = gyro.dmpInitialize();
gyro.setXGyroOffset(GYRO_GX_OFFSET);
gyro.setYGyroOffset(GYRO_GY_OFFSET);
gyro.setZGyroOffset(GYRO_GZ_OFFSET);
gyro.setXAccelOffset(GYRO_AX_OFFSET);
gyro.setYAccelOffset(GYRO_AY_OFFSET);
gyro.setZAccelOffset(GYRO_AZ_OFFSET);
if (devStatus == 0) {
gyro.setDMPEnabled(true);
lastMicros = micros();
attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), dmpDataReady, RISING);
gyroIntStatus = gyro.getIntStatus();
packetSize = gyro.dmpGetFIFOPacketSize();
}else if(devStatus == 1) return EC_DMP_MEMORY_WRITING_FAILED;
else if(devStatus == 2) return EC_DMP_CONFIG_WRITING_FAILED;
}else return EC_NO_CONNECTION;
loops_before_calibration = 0;
return EC_NO_ERROR;
}
void GYRO::update(void){
//temperature = gyro.getTemperature()/340.0+36.53; //When discommenting this line i get rarely FIFO overflows, but without it, i have not recived eaither one
gyroscopeUpdated = false;
while (!interrupt && fifoCount < packetSize){
if (interrupt && fifoCount < packetSize){
fifoCount = gyro.getFIFOCount();
}
}
interrupt = false;
gyroIntStatus = gyro.getIntStatus();
fifoCount = gyro.getFIFOCount();
if ((gyroIntStatus & _BV(MPU6050_INTERRUPT_FIFO_OFLOW_BIT)) || fifoCount >= 1024){
gyro.resetFIFO();
fifoCount = gyro.getFIFOCount();
Serial.println(F("FIFO overflow!"));
}else if (gyroIntStatus & _BV(MPU6050_INTERRUPT_DMP_INT_BIT)){
while (fifoCount < packetSize) fifoCount = gyro.getFIFOCount();
gyro.getFIFOBytes(fifoBuffer, packetSize);
actualMicros = micros();
microsSpent = actualMicros - lastMicros;
lastMicros = actualMicros;
fifoCount -= packetSize;
gyro.dmpGetQuaternion(&q, fifoBuffer);
gyro.dmpGetGravity(&gravity, &q);
gyro.dmpGetYawPitchRoll(ypr, &q, &gravity);
gyro.dmpGetAccel(&rawAccelerometer, fifoBuffer);
gyro.dmpGetLinearAccel(&rawAccelerometer, &rawAccelerometer, &gravity);
//gyro.dmpGetLinearAccelInWorld(&rawAccelerometer, &rawAccelerometer, &q);
accelerometer.x = rawAccelerometer.x/8192.0*9.8;
accelerometer.y = rawAccelerometer.y/8192.0*9.8;
accelerometer.z = rawAccelerometer.z/8192.0*9.8;
gyroscope.x = ypr[2];
gyroscope.y = ypr[1]*-1;
gyroscope.z = ypr[0]*-1;
if(loops_before_calibration > CALIBRATION_LOOPS){
gyroscopeUpdated = true;
}else loops_before_calibration++;
}
}
Example code(To upload to arduino):
#include <GYRO.h>
#include <helper_3dmath.h>
GYRO gyro = GYRO();
VectorFloat gravity;
VectorFloat gyroscope;
VectorDouble accelerometer;
void setup() {
Serial.begin(115200);
Serial.println(gyro.begin());
}
void loop() {
gyro.update();
if(gyro.isGyroscopeUpdated()){
gravity = gyro.getGravity();
accelerometer = gyro.getAccelerometer();
gyroscope = gyro.getGyroscope();
Serial.print("gyroscope\t");
Serial.print(gyroscope.x * 180/M_PI);
Serial.print("\t");
Serial.print(gyroscope.y * 180/M_PI);
Serial.print("\t");
Serial.print(gyroscope.z * 180/M_PI);
Serial.print("\taccelerometer\t");
Serial.print(accelerometer.x);
Serial.print("\t");
Serial.print(accelerometer.y);
Serial.print("\t");
Serial.print(accelerometer.z);
Serial.print("\tgravity\t");
Serial.print(gravity.x);
Serial.print("\t");
Serial.print(gravity.y);
Serial.print("\t");
Serial.print(gravity.z);
Serial.print("\ttemperature\t");
Serial.print(gyro.getTemperature());
Serial.print(", micros: ");
Serial.println(gyro.getMicrosSpent());
}
}
You have to provide your own offsets. To obtain it, you can use this link
I hope this code is useful.
I know it is too late but maybe will help others...
The first MPU6050 initialization part in the setup() is done before even the mux initialized.
So you have to do the following, inside the setup(), at the right order:
initialize wire
initialize the outputs for the mux
select the first MPU using the right output levels
initialize the first MPU6050
select the second MPU using the right output levels
initialize the second MPU6050
select the third MPU using the right output levels
initialize the third MPU6050

Resources