How to control multiple SPI's - arduino

I am having a weeny trouble with my SAMD21 board. I have got this starter kit (schematics) and I want to add some more sensors. They use SPI, so I programmed them. Since SAMD21 got the code it lag's everytime, when code reache's the sensor begin function. Please give me some advice, how to control both SPI's correctly and avoid lags.
*lags are total lags - SAMD21 do nothing after reaching the begin function.
*schematics: http://kit.sciencein.cz/wiki/images/b/be/MainBoard_v2.0_RevB_SCH.png
*sorry for mistakes in the code (it is long code cut to short)
*my code:
#include <Adafruit_BME280.h> // include Adafruit BME280 library
#include <Adafruit_INA219.h> // include INA219
#include <SD.h> // include Arduino SD library
#include "Open_Cansat_GPS.h"
//include our new sensors
#include "MQ131.h"
#include <Wire.h>
#include <SPI.h>
#include "RFM69.h" // include RFM69 library
// Local
#define PC_BAUDRATE 115200
#define MS_DELAY 0 // Number of milliseconds between data sending and LED signalization
#define LED_DELAY 100
#define Serial SerialUSB
RTCZero rtc;
// RFM69
#define NETWORKID 0 // Must be the same for all nodes (0 to 255)
#define MYNODEID 1 // My node ID (0 to 255)
#define TONODEID 2 // Destination node ID (0 to 254, 255 = broadcast)
#define FREQUENCY RF69_433MHZ // Frequency set up
#define FREQUENCYSPECIFIC 433000000 // Should be value in Hz, now 433 Mhz will be set
#define CHIP_SELECT_PIN 43 //radio chip select
#define INTERUP_PIN 9 //radio interrupt
// BME280 SETTING
#define BME280_ADDRESS_OPEN_CANSAT 0x77
#define SEALEVELPRESSURE_HPA 1013.25
//OZONE2CLICK
const byte pinSS = 2; //cs pin
const byte pinRDY = 12;
const byte pinSCK = 13;
const byte O2Pin = 10;
#define DcPin 8
// SD card
#define sd_cs_pin 35 // set SD's chip select pin (according to the circuit)
// create object 'rf69' from the library, which will
// be used to access the library methods by a dot notation
RFM69 radio(CHIP_SELECT_PIN, INTERUP_PIN, true);
// define our own struct data type with variables; used to send data
typedef struct
{
int16_t messageId;
uint16_t year;
uint8_t month;
uint8_t day;
uint8_t hour;
uint8_t minute;
uint8_t sec;
float longitude;
float latitude;
uint8_t num_of_satelites;
float temperature;
float pressure;
float altitude;
float humidity_bme280;
float voltage_shunt;
float voltage_bus;
float current_mA;
float voltage_load;
int16_t rssi;
} messageOut;
messageOut cansatdata; //create the struct variable
// create object 'bme' from the library, which will
// be used to access the library methods by a dot notation
Adafruit_BME280 bme;
// create object 'ina219' from the library with address 0x40
// (according to the circuit, which will be used to access the
// library methods by a dot notation
Adafruit_INA219 ina219(0x40);
// create object 'gps' from the library
OpenCansatGPS gps;
// SD card
File file; // SD library variable
// LEDS
#define D13_led_pin 42 // D13 LED
#define M_led_pin 36 // MLED
// Local variables
int idCounter = 1;
bool isBmeOk = true;
bool isSdOk = true;
bool isRadioOk = true;
bool isGpsConnected = true;
// My variables
float NH3Data;
float COData;
float NO2Data;
float PPMO2;
float PPBO2;
float MGM3O2;
float UGM3O2;
float SSmoke1;
float SSmoke2;
float SSmoke3;
float ESmoke1;
float ESmoke2;
float ESmoke3;
int DataCounter = 0;
void OZONE2CLICKCalibrate ()
{
Serial.println("2");
//MQ131.begin(pinSS, pinRDY, O2Pin, LOW_CONCENTRATION, 10000); //(int _pinCS, int _pinRDY, int _pinPower, MQ131Model _model, int _RL)
Serial.println("99");
Serial.println("Calibration in progress...");
MQ131.calibrate();
Serial.println("Calibration done!");
Serial.print("R0 = ");
Serial.print(MQ131.getR0());
Serial.println(" Ohms");
Serial.print("Time to heat = ");
Serial.print(MQ131.getTimeToRead());
Serial.println(" s");
}
void OZONE2CLICKMeasure ()
{
Serial.println("Sampling...");
MQ131.sample();
Serial.print("Concentration O3 : ");
PPMO2 = MQ131.getO3(PPM);
Serial.print(PPMO2);
Serial.println(" ppm");
Serial.print("Concentration O3 : ");
PPBO2 = MQ131.getO3(PPB);
Serial.print(PPBO2);
Serial.println(" ppb");
Serial.print("Concentration O3 : ");
MGM3O2 = MQ131.getO3(MG_M3);
Serial.print(MGM3O2);
Serial.println(" mg/m3");
Serial.print("Concentration O3 : ");
UGM3O2 = MQ131.getO3(UG_M3);
Serial.print(UGM3O2);
Serial.println(" ug/m3");
}
void setup()
{
pinMode(pinSS, OUTPUT);
digitalWrite(pinSS, HIGH);
delay(10000);
Serial.begin(PC_BAUDRATE);
// wait for the Arduino serial (on your PC) to connect
// please, open the Arduino serial console (right top corner)
// note that the port may change after uploading the sketch
// COMMENT OUT FOR USAGE WITHOUT A PC!
// while(!Serial);
Serial.println("openCanSat PRO");
Serial.print("Node ");
Serial.print(MYNODEID,DEC);
Serial.println(" ready");
// begin communication with the BME280 on the previously specified address
// print an error to the serial in case the sensor is not found
if (!bme.begin(BME280_ADDRESS_OPEN_CANSAT))
{
isBmeOk = false;
Serial.println("Could not find a valid BME280 sensor, check wiring!");
return;
}
// begin communication with the INA219
ina219.begin();
// check of Gps is connected
Wire.beginTransmission(0x42); // 42 is addres of GPS
int error = Wire.endTransmission();
if (error != 0)
{
isGpsConnected = false;
}
// begin communication with gps
gps.begin();
// Uncomment when you want to see debug prints from GPS library
// gps.debugPrintOn(57600);
if(!radio.initialize(FREQUENCY, MYNODEID, NETWORKID))
{
isRadioOk = false;
Serial.println("RFM69HW initialization failed!");
}
else
{
radio.setFrequency(FREQUENCYSPECIFIC);
radio.setHighPower(true); // Always use this for RFM69HW
}
pinMode(D13_led_pin, OUTPUT);
pinMode(DcPin, OUTPUT);
pinMode(MICS6814Pin, OUTPUT);
pinMode(MICSVZ89TEPin, OUTPUT);
pinMode(O2Pin, OUTPUT);
GyroscopeTurnOn();
}
void loop()
{
cansatdata.messageId = idCounter;
GyroscopeMeasure();
LandingChecker();
Serial.println("MessageId = " + static_cast<String>(cansatdata.messageId));
cansatdata.temperature = 0;
cansatdata.pressure = 0;
cansatdata.altitude = 0;
if(isBmeOk)
{
cansatdata.temperature += bme.readTemperature();
cansatdata.pressure += bme.readPressure() / 100.0F;
cansatdata.altitude += bme.readAltitude(SEALEVELPRESSURE_HPA);
cansatdata.humidity_bme280 = bme.readHumidity();
}
Serial.println("Temperature = " + static_cast<String>(cansatdata.temperature) + " *C");
Serial.println("Pressure = " + static_cast<String>(cansatdata.pressure) + " Pa");
Serial.println("Approx altitude = " + static_cast<String>(cansatdata.altitude) + " m");
Serial.println("Humidity = " + static_cast<String>(cansatdata.humidity_bme280) + " %");
// read values from INA219 into structure
cansatdata.voltage_shunt = ina219.getShuntVoltage_mV();
cansatdata.voltage_bus = ina219.getBusVoltage_V();
cansatdata.current_mA = ina219.getCurrent_mA();
cansatdata.voltage_load = cansatdata.voltage_bus + (cansatdata.voltage_shunt / 1000);
Serial.println("Shunt Voltage: " + static_cast<String>(cansatdata.voltage_shunt) + " mV");
Serial.println("Bus Voltage: " + static_cast<String>(cansatdata.voltage_bus) + " V");
Serial.println("Current: " + static_cast<String>(cansatdata.current_mA) + " mA");
Serial.println("Load Voltage: " + static_cast<String>(cansatdata.voltage_load) + " V");
// Initialize GPS
cansatdata.year = 0;
cansatdata.month = 0 ;
cansatdata.day = 0;
cansatdata.hour = 0;
cansatdata.minute = 0;
cansatdata.sec = 0;
cansatdata.latitude = 0;
cansatdata.longitude = 0;
cansatdata.num_of_satelites = 0;
// save start time in millisec
uint32_t start = millis();
// END LED BLINK
digitalWrite(D13_led_pin, LOW);
pinMode(M_led_pin, INPUT);
// END LED BLINK
if(isGpsConnected)
{
if (gps.scan(250))
{
cansatdata.year = gps.getYear();
cansatdata.month = gps.getMonth();
cansatdata.day = gps.getDay();
cansatdata.hour = gps.getHour();
cansatdata.minute = gps.getMinute();
cansatdata.sec = gps.getSecond();
cansatdata.latitude = gps.getLat();
cansatdata.longitude = gps.getLon();
cansatdata.num_of_satelites = gps.getNumberOfSatellites();
Serial.println(String("Time to find fix: ") + (millis() - start) + String("ms"));
Serial.println(String("Datetime: ") + String(cansatdata.year) + "/"+ String(cansatdata.month) + "/"+ String(cansatdata.day) + " " + String(cansatdata.hour) + ":"+ String(cansatdata.minute) + ":"+ String(cansatdata.sec));
Serial.println(String("Lat: ") + String(cansatdata.latitude, 7));
Serial.println(String("Lon: ") + String(cansatdata.longitude, 7));
Serial.println(String("Num of sats: ") + String(cansatdata.num_of_satelites));
Serial.println();
}
else
{
Serial.println("Gps have no satelit to fix.");
}
}
// RFM69HW
cansatdata.rssi = 0;
if(isRadioOk)
{
cansatdata.rssi = radio.RSSI;
Serial.println("Signal = " + static_cast<String>(radio.RSSI));
radio.send(TONODEID, (const void*)&cansatdata, sizeof(cansatdata));
}
Serial.println();
// START LED hart beat
pinMode(M_led_pin, OUTPUT);
digitalWrite(D13_led_pin, HIGH);
digitalWrite(M_led_pin, HIGH);
// START LED hart beat
if(!isGpsConnected)
{
delay(200);
}
idCounter ++;
}

Related

PPM output is noisy when reading from sensors over i2c

Please excuse me for the lengthiness of the problem but its beyond my knowhow, I dont know where else to go.
I am trying to send a PPM signal to a FlySkyi10 radio over the trainer cable. When using the PPM code below I am able to send the correct PPM signals to my radio.
//this programm will put out a PPM signal
//////////////////////CONFIGURATION///////////////////////////////
#define chanel_number 8 //set the number of chanels
#define default_servo_value 1500 //set the default servo value
#define PPM_FrLen 22500 //set the PPM frame length in microseconds (1ms = 1000µs)
#define PPM_PulseLen 300 //set the pulse length
#define onState 1 //set polarity of the pulses: 1 is positive, 0 is negative
#define sigPin 10 //set PPM signal output pin on the arduino
//////////////////////////////////////////////////////////////////
/*this array holds the servo values for the ppm signal
change theese values in your code (usually servo values move between 1000 and 2000)*/
int ppm[chanel_number];
void setup(){
//initiallize default ppm values
for(int i=0; i<chanel_number; i++){
ppm[i]= default_servo_value;
}
pinMode(sigPin, OUTPUT);
digitalWrite(sigPin, !onState); //set the PPM signal pin to the default state (off)
cli();
TCCR1A = 0; // set entire TCCR1 register to 0
TCCR1B = 0;
OCR1A = 100; // compare match register, change this
TCCR1B |= (1 << WGM12); // turn on CTC mode
TCCR1B |= (1 << CS11); // 8 prescaler: 0,5 microseconds at 16mhz
TIMSK1 |= (1 << OCIE1A); // enable timer compare interrupt
sei();
}
void loop(){
//put main code here
static int val = 1;
ppm[0] = ppm[0] + val;
if(ppm[0] >= 2000){ val = -1; }
if(ppm[0] <= 1000){ val = 1; }
delay(10);
}
ISR(TIMER1_COMPA_vect){ //leave this alone
static boolean state = true;
TCNT1 = 0;
if(state) { //start pulse
digitalWrite(sigPin, onState);
OCR1A = PPM_PulseLen * 2;
state = false;
}
else{ //end pulse and calculate when to start the next pulse
static byte cur_chan_numb;
static unsigned int calc_rest;
digitalWrite(sigPin, !onState);
state = true;
if(cur_chan_numb >= chanel_number){
cur_chan_numb = 0;
calc_rest = calc_rest + PPM_PulseLen;//
OCR1A = (PPM_FrLen - calc_rest) * 2;
calc_rest = 0;
}
else{
OCR1A = (ppm[cur_chan_numb] - PPM_PulseLen) * 2;
calc_rest = calc_rest + ppm[cur_chan_numb];
cur_chan_numb++;
}
}
}
But, the problem comes in when I read data from a sensor over i2c and some other functions. As soon as I use the i2c code, the PPM signal becomes noisy, and what should be a 1500ms signal, has noise of +/-20ms.
I dont want to make this post too bulky, I have used the i2c library for the LSM9DS0 to read sensor data. I have not used interrupts anywhere and I will have to have a closer look at the library. unfortunately i dont understand much of it. The simplified code for reading from the seensors is below. the website for the libraries is here: https://learn.adafruit.com/adafruit-lsm9ds0-accelerometer-gyro-magnetometer-9-dof-breakouts/arduino-code
#include <Wire.h>
#include <SPI.h>
#include <Adafruit_LSM9DS0.h>
#include <Adafruit_Sensor.h> // not used in this demo but required!
// i2c
Adafruit_LSM9DS0 lsm = Adafruit_LSM9DS0();
// You can also use software SPI
//Adafruit_LSM9DS0 lsm = Adafruit_LSM9DS0(13, 12, 11, 10, 9);
// Or hardware SPI! In this case, only CS pins are passed in
//Adafruit_LSM9DS0 lsm = Adafruit_LSM9DS0(10, 9);
void setupSensor()
{
// 1.) Set the accelerometer range
lsm.setupAccel(lsm.LSM9DS0_ACCELRANGE_2G);
//lsm.setupAccel(lsm.LSM9DS0_ACCELRANGE_4G);
//lsm.setupAccel(lsm.LSM9DS0_ACCELRANGE_6G);
//lsm.setupAccel(lsm.LSM9DS0_ACCELRANGE_8G);
//lsm.setupAccel(lsm.LSM9DS0_ACCELRANGE_16G);
// 2.) Set the magnetometer sensitivity
lsm.setupMag(lsm.LSM9DS0_MAGGAIN_2GAUSS);
//lsm.setupMag(lsm.LSM9DS0_MAGGAIN_4GAUSS);
//lsm.setupMag(lsm.LSM9DS0_MAGGAIN_8GAUSS);
//lsm.setupMag(lsm.LSM9DS0_MAGGAIN_12GAUSS);
// 3.) Setup the gyroscope
lsm.setupGyro(lsm.LSM9DS0_GYROSCALE_245DPS);
//lsm.setupGyro(lsm.LSM9DS0_GYROSCALE_500DPS);
//lsm.setupGyro(lsm.LSM9DS0_GYROSCALE_2000DPS);
}
void setup()
{
#ifndef ESP8266
while (!Serial); // will pause Zero, Leonardo, etc until serial console opens
#endif
Serial.begin(9600);
Serial.println("LSM raw read demo");
// Try to initialise and warn if we couldn't detect the chip
if (!lsm.begin())
{
Serial.println("Oops ... unable to initialize the LSM9DS0. Check your wiring!");
while (1);
}
Serial.println("Found LSM9DS0 9DOF");
Serial.println("");
Serial.println("");
}
void loop(void)
{
/* Get a new sensor event */
sensors_event_t accel, mag, gyro, temp;
lsm.getEvent(&accel, &mag, &gyro, &temp);
// print out accelleration data
Serial.print("Accel X: "); Serial.print(accel.acceleration.x); Serial.print(" ");
Serial.print(" \tY: "); Serial.print(accel.acceleration.y); Serial.print(" ");
Serial.print(" \tZ: "); Serial.print(accel.acceleration.z); Serial.println(" \tm/s^2");
// print out magnetometer data
Serial.print("Magn. X: "); Serial.print(mag.magnetic.x); Serial.print(" ");
Serial.print(" \tY: "); Serial.print(mag.magnetic.y); Serial.print(" ");
Serial.print(" \tZ: "); Serial.print(mag.magnetic.z); Serial.println(" \tgauss");
// print out gyroscopic data
Serial.print("Gyro X: "); Serial.print(gyro.gyro.x); Serial.print(" ");
Serial.print(" \tY: "); Serial.print(gyro.gyro.y); Serial.print(" ");
Serial.print(" \tZ: "); Serial.print(gyro.gyro.z); Serial.println(" \tdps");
// print out temperature data
Serial.print("Temp: "); Serial.print(temp.temperature); Serial.println(" *C");
Serial.println("**********************\n");
delay(250);
}
Does anyone have an suggestions?
I changed the method of reading data from the sensors to SPI, which solved the problem. All noise in the ppm signal has been eliminated.

Reading and transferring encoder data from slave Arduino to master Arduino over SPI

My goal is to transfer a speed value from an encoder from a slave Arduino to a master Arduino via SPI. I am currently getting zeros on the master side serial print and I'm not sure what I am doing wrong. I have increased the amount of time to wait several times to see if it was a processing time issue but I had it waiting for 100mS with still no change. I know an unsigned int is 4 bytes and I am unsure if a union is the best option in this case seeing I might be overwriting my data due to the separate interrupts but I am unsure. I thought to use a struct since I'll have to move to transferring an array of floats and ints over SPI from various sensors including this encoder later. Below is my code and thank you for any help received:
Slave
#include "math.h"
#define M_PI
byte command = 0;
const int encoder_a = 2; // Green - pin 2 - Digital
const int encoder_b = 3; // White - pin 3 - Digital
long encoder = 0;
int Diameter = 6; // inches
float previous_distance = 0;
unsigned long previous_time = 0;
void setup (void)
{
Serial.begin(115200);
pinMode(MOSI, INPUT);
pinMode(SCK, INPUT);
pinMode(SS, INPUT);
pinMode(MISO, OUTPUT);
// turn on SPI in slave mode
SPCR |= _BV(SPE);
// turn on interrupts
SPCR |= _BV(SPIE);
pinMode(encoder_a, INPUT_PULLUP);
pinMode(encoder_b, INPUT_PULLUP);
attachInterrupt(0, encoderPinChangeA, CHANGE);
attachInterrupt(1, encoderPinChangeB, CHANGE);
}
// SPI interrupt routine
ISR (SPI_STC_vect)
{
union Data{
float f;
byte buff[4];}
data;
byte c = SPDR;
data.f = assembly_speed();
command = c;
switch (command)
{
// no command? then this is the command
case 0:
SPDR = 0;
break;
// incoming byte, return byte result
case 'a':
SPDR = data.buff[0];
break;
// incoming byte, return byte result
case 'b':
SPDR = data.buff[1];
break;
// incoming byte, return byte result
case 'c':
SPDR = data.buff[2];
break;
// incoming byte, return byte result
case 'd':
SPDR = data.buff[3];
break;
}
}
void loop (void)
{
// if SPI not active, clear current command
if (digitalRead (SS) == HIGH)
command = 0;
}
void encoderPinChangeA()
{
encoder += digitalRead(encoder_a) == digitalRead(encoder_b) ? -1 : 1;
}
void encoderPinChangeB()
{
encoder += digitalRead(encoder_a) != digitalRead(encoder_b) ? -1 : 1;
}
float distance_rolled()
{
float distance_traveled = (float (rotation()) / 8) * PI * Diameter;
return distance_traveled;
}
int rotation()
{
float eigth_rotation = encoder / 300;
return eigth_rotation;
}
float assembly_speed()
{
float current_distance = (float (rotation()) / 8) * PI * Diameter;
unsigned long current_time = millis();
unsigned long assemblySpeed = (((current_distance - previous_distance) /
12) * 1000) / (current_time - previous_time); // gives ft/s
previous_distance = current_distance;
previous_time = current_time;
return assemblySpeed;
}
Master
#include <SPI.h>
void setup (void)
{
pinMode(MOSI, OUTPUT);
pinMode(MISO, INPUT);
pinMode(SCK, OUTPUT);
pinMode(SS, OUTPUT);
Serial.begin (115200);
Serial.println ();
digitalWrite(SS, HIGH);
SPI.begin ();
SPI.setClockDivider(SPI_CLOCK_DIV8);
}
byte transferAndWait (const byte what)
{
byte a = SPI.transfer (what);
delayMicroseconds(10000);
return a;
}
union Data
{
float f;
byte buff[4];
}
data;
void loop (void)
{
digitalWrite(SS, LOW);
transferAndWait ('a');
data.buff[0] = transferAndWait ('b');
data.buff[1] = transferAndWait ('c');
data.buff[2] = transferAndWait ('d');
data.buff[3] = transferAndWait (0);
digitalWrite(SS, HIGH);
Serial.print("data.f = ");Serial.print(data.f);Serial.println(" Ft/s");
delay(200);
}

Merging two arduino sketches

I have been working on a project. I have two sketches. One is to get GPS location and one is send location via SMS (GSM Module). I want to combine both sketches.
GPS sketch:
#include <SoftwareSerial.h>
#include <TinyGPS.h>
//long lat,lon; // create variable for latitude and longitude object
float flat, flon;
SoftwareSerial gpsSerial(4, 3); // create gps sensor connection
TinyGPS gps; // create gps object
void setup(){
Serial.begin(9600); // connect serial
gpsSerial.begin(9600); // connect gps sensor
}
static void print_float(float val, float invalid, int len, int prec)
{
if (val == invalid)
{
while (len-- > 1)
Serial.print('*');
Serial.print(' ');
}
else
{
Serial.print(val, prec);
int vi = abs((int)val);
int flen = prec + (val < 0.0 ? 2 : 1); // . and -
flen += vi >= 1000 ? 4 : vi >= 100 ? 3 : vi >= 10 ? 2 : 1;
for (int i=flen; i<len; ++i)
Serial.print(' ');
}
// smartdelay(0);
}
void loop(){
while(gpsSerial.available()){ // check for gps data
if(gps.encode(gpsSerial.read())){ // encode gps data
// gps.get_position(&lat,&lon); // get latitude and longitude
gps.f_get_position(&flat, &flon);
String lat = String(flat,6);
String lon = String(flon,6);
Serial.print(lat);
Serial.print(' ');
Serial.println(lon);
}
}
}
GSM sketch:
#include <SoftwareSerial.h>
SoftwareSerial mySerial(9, 10);
void setup()
{
mySerial.begin(9600); // Setting the baud rate of GSM Module
Serial.begin(9600); // Setting the baud rate of Serial Monitor (Arduino)
delay(100);
}
int index=0;
long dlat=0,dlong=0;
char st[256],st1[256],st2[256];
void RecieveMessage()
{
mySerial.println("AT+CNMI=2,2,0,0,0"); // AT Command to receive a live SMS
// mySerial.println("cheking");
// mySerial.println(string);
}
void loop()
{
if (Serial.available()>0)
RecieveMessage();
if (mySerial.available()>0)
{
//int st;
st[index++] = mySerial.read();
//Serial.write(st[index-1]);
if(index>=51&&index<=63){
st1[index-51]=st[index-1];
Serial.write(st1[index-51]);
}
if(index>=65&&index<=77){
st2[index-65]=st[index-1];
Serial.write(st2[index-65]);
}
/*if(index==77)
{
int i=0;
mySerial.print(st1);
for(i=0;i<13;i++)
{
if(st1[i]!='.')
dlat=dlat*10+(st1[i]-'0');
if(st2[i]!='.')
dlong=dlong*10+(st2[i]-'0');
//Serial.print(dlat);
}
//Serial.print(dlat);
//Serial.print(" ");
//Serial.print(dlong);
*/
}
}
I want to merge these two sketches so that I can send location via GSM sketch and receive location through GPS sketch.
Any help will be appreciated.
Thanks.
The following way you can merge your two sketches :
#include <AltSoftSerial.h>
#include <SoftwareSerial.h>
#include <TinyGPS.h>
//long lat,lon; // create variable for latitude and longitude object
float flat, flon;
SoftwareSerial gpsSerial(4, 3); // create gps sensor connection
TinyGPS gps; // create gps object
static const int RXPin = 8, TXPin = 9;
AltSoftSerial mySerial(RXPin, TXPin);
int index=0;
long dlat=0,dlong=0;
char st[256],st1[256],st2[256];
void RecieveMessage()
{
mySerial.println("AT+CNMI=2,2,0,0,0"); // AT Command to receive a live SMS
// mySerial.println("cheking");
// mySerial.println(string);
}
void setup(){
Serial.begin(9600); // connect serial
gpsSerial.begin(9600); // connect gps sensor
mySerial.begin(9600); // Setting the baud rate of GSM Module
delay(100);
}
static void print_float(float val, float invalid, int len, int prec)
{
if (val == invalid)
{
while (len-- > 1)
Serial.print('*');
Serial.print(' ');
}
else
{
Serial.print(val, prec);
int vi = abs((int)val);
int flen = prec + (val < 0.0 ? 2 : 1); // . and -
flen += vi >= 1000 ? 4 : vi >= 100 ? 3 : vi >= 10 ? 2 : 1;
for (int i=flen; i<len; ++i)
Serial.print(' ');
}
// smartdelay(0);
}
void loop(){
while(gpsSerial.available()){ // check for gps data
if(gps.encode(gpsSerial.read())){ // encode gps data
// gps.get_position(&lat,&lon); // get latitude and longitude
gps.f_get_position(&flat, &flon);
String lat = String(flat,6);
String lon = String(flon,6);
Serial.print(lat);
Serial.print(' ');
Serial.println(lon);
if (Serial.available()>0)
RecieveMessage();
if (mySerial.available()>0)
{
//int st;
st[index++] = mySerial.read();
//Serial.write(st[index-1]);
if(index>=51&&index<=63){
st1[index-51]=st[index-1];
Serial.write(st1[index-51]);
}
if(index>=65&&index<=77){
st2[index-65]=st[index-1];
Serial.write(st2[index-65]);
}
/*if(index==77)
{
int i=0;
mySerial.print(st1);
for(i=0;i<13;i++)
{
if(st1[i]!='.')
dlat=dlat*10+(st1[i]-'0');
if(st2[i]!='.')
dlong=dlong*10+(st2[i]-'0');
//Serial.print(dlat);
}
//Serial.print(dlat);
//Serial.print(" ");
//Serial.print(dlong);
*/
}
}
}
}
P.S : I have changed the pins for GPS and rest part is same irrespective of adding AltSoftSerial it is a library same as SoftwareSerial (Download it from manage libraries and it requires pins 8 and 9)

Why does the SD card stop logging without error?

The following sketch is for an Arduino Nano clone. It waits for a START command then collects data from an I2C slave, assembles it for logging on an SD card, writes it to the card, prints it to the serial monitor and repeats. I've tested and retested. The SD card logfile ALWAYS stops after logging the header and 3 out of 30 lines of data, but the serial monitor shows all the expected data. Never in any of my tests was an SD write error generated.
I'd appreciate any ideas as to why the SD stops logging and how to fix it.
Arduino Sketch
#include <Wire.h>
#include <Servo.h>
#include <SD.h>
#include <SPI.h>
// Uncomment the #define below to enable internal polling of data.
#define POLLING_ENABLED
//define slave i2c address
#define I2C_SLAVE_ADDRESS 9
/* ===================================
Arduino Nano Connections
ESC (PWM) Signal - Pin 9 (1000ms min, 2000ms max)
S.Port Signal - Pin 10
SPI Connections
MOSI = Pin 11
MISO = Pin 12
SCLK = PIN 13
I2C Connections
SDA = Pin A4
SCL = Pin A5
Start/Stop Switches
Start = Pin 2 => INT0
Stop = Pin 3 => INT1
===================================*/
Servo esc; // Servo object for the ESC - PIN 9
const unsigned long pause = 800; // Number of ms between readings
const unsigned long testDelay = 30000; // Number of ms between tests
const int CS_pin = 10; // Pin to use for CS (SS) on your board
const int Startpin = 2;
const int Stoppin = 3;
const int readings = 3; // Number of readings to take at every step
const int steps = 5; // Number of steps to stop the ESC and take readings
const byte HALT = 0;
int ESC = 0;
int throttle = 0;
int increment;
volatile bool STOP = 0;
volatile bool START = 0;
const String header = "% Thr,Thrust,Curr,Volts,RPM,Cell1,Cell2,Cell3,Cell4,Cell5,Cell6";
char buffer0[33]; // Buffer for I2C received data
char buffer1[33]; // Buffer for I2C received data
String logEntry = " GOT NO DATA "; //52 bytes
void setup() {
Wire.begin();
Serial.begin(115200);
pinMode(Startpin, INPUT_PULLUP);
pinMode(Stoppin, INPUT_PULLUP);
// Attach an interrupt to the ISR vector
attachInterrupt(digitalPinToInterrupt(Startpin), start_ISR, LOW);
attachInterrupt(digitalPinToInterrupt(Stoppin), stop_ISR, LOW);
esc.attach(9, 1000, 2000);
// attaches the ESC on pin 9 to the servo object and sets min and max pulse width
esc.write(HALT); // Shut down Motor NOW!
increment = 180 / (steps - 1);
// Number of degrees to move servo (ESC) per step (servo travel is 0-180 degrees so 180 = 100% throttle)
delay(500);
Serial.println(" Thrust Meter I2C Master");
//Print program name
//Initialize SD Card
if (!SD.begin(CS_pin)) {
Serial.println("Card Failure");
}
Serial.println("Card Ready");
//Write Log File Header to SD Card
writeSD(header);
Serial.println(header);
}
void loop() {
if (START) {
Serial.println("Start Pressed");
while (!STOP) {
for (throttle = 0; throttle <= 180; throttle += increment) {
for (int x = 0; x < readings; x++) {
if (STOP) {
esc.write(HALT); // Shut down Motor NOW!
Serial.println("Halting Motor");
} else {
wait (pause);
esc.write(throttle); // increment the ESC
wait (200);
ESC = throttle * 100 / 180;
getData(buffer0);
wait (100);
getData(buffer1);
String logEntry = String(ESC) + "," + String(buffer1) + "," + String(buffer0);
writeSD(logEntry);
Serial.println(logEntry);
}
}
}
for (throttle = 180; throttle >= 0; throttle -= increment) {
for (int x = 0; x < readings; x++) {
if (STOP) {
esc.write(HALT); // Shut down Motor NOW!
Serial.println("Halting Motor");
} else {
wait (pause);
esc.write(throttle); // increment the ESC
wait (200);
ESC = throttle * 100 / 180;
getData(buffer0);
wait (100);
getData(buffer1);
String logEntry = String(ESC) + "," + String(buffer1) + "," + String(buffer0);
writeSD(logEntry);
Serial.println(logEntry);
}
}
}
Serial.println("End of Test Pass");
wait (testDelay);
}
esc.write(HALT); // Shut down Motor NOW!
}
}
void writeSD(String logdata) {
File logFile = SD.open("NANO_LOG.csv", FILE_WRITE);
if (logFile) {
logFile.println(logdata);
logFile.close();
} else {
Serial.println("Error writing log data");
}
}
void wait(unsigned long i) {
unsigned long time = millis() + i;
while(millis()<time) { }
}
void start_ISR() {
START = 1;
STOP = 0;
}
void stop_ISR() {
STOP = 1;
START = 0;
}
void getData(char* buff) {
Wire.requestFrom(9, 32);
for (byte i = 0; i < 32 && Wire.available(); ++i) {
buff[i] = Wire.read();
if (buff[i] == '#') {
buff[i] = '\0';
break;
}
}
}
This is the SD card contents:
% Thr,Thrust,Curr,Volts,RPM,Cell1,Cell2,Cell3,Cell4,Cell5,Cell6
0,-12,0.00,15.76,0,3.10,4.20,3.96,3.96,0.00,0.00
0,-12,0.00,15.76,0,3.10,4.20,3.96,3.96,0.00,0.00
0,128,0.00,15.76,0,3.10,4.20,3.96,3.96,0.00,0.00
This is the output from the serial monitor:
Thrust Meter I2C Master
Card Ready
% Thr,Thrust,Curr,Volts,RPM,Cell1,Cell2,Cell3,Cell4,Cell5,Cell6
Start Pressed
0,-12,0.00,15.76,0,3.10,4.20,3.96,3.96,0.00,0.00
0,-12,0.00,15.76,0,3.10,4.20,3.96,3.96,0.00,0.00
0,128,0.00,15.76,0,3.10,4.20,3.96,3.96,0.00,0.00
25,2062,0.00,15.76,0,3.10,4.20,3.96,3.96,0.00,0.00
25,2520,0.00,15.75,0,3.10,4.20,3.96,3.96,0.00,0.00
25,2710,0.00,15.75,0,3.10,4.20,3.96,3.96,0.00,0.00
50,519,0.00,15.75,0,3.10,4.20,3.96,3.96,0.00,0.00
50,216,0.00,15.76,0,3.10,4.20,3.96,3.96,0.00,0.00
50,2288,0.00,15.76,0,3.10,4.20,3.96,3.96,0.00,0.00
75,890,0.00,15.76,0,3.10,4.20,3.96,3.96,0.00,0.00
75,891,0.00,15.76,0,3.10,4.20,3.96,3.96,0.00,0.00
75,1386,0.00,15.76,0,3.10,4.20,3.96,3.96,0.00,0.00
100,2621,0.00,15.76,0,3.10,4.20,3.96,3.96,0.00,0.00
100,2424,0.00,15.76,0,3.10,4.20,3.96,3.96,0.00,0.00
100,692,0.00,15.76,0,3.10,4.20,3.96,3.96,0.00,0.00
100,3409,0.00,15.76,0,3.10,4.20,3.96,3.96,0.00,0.00
100,227,0.00,15.76,0,3.10,4.20,3.96,3.96,0.00,0.00
100,3349,0.00,15.76,0,3.10,4.20,3.96,3.96,0.00,0.00
75,2220,0.00,15.76,0,3.10,4.20,3.96,3.96,0.00,0.00
75,2249,0.00,15.76,0,3.10,4.20,3.96,3.96,0.00,0.00
75,509,0.00,15.76,0,3.10,4.20,3.96,3.96,0.00,0.00
50,1977,0.00,15.76,0,3.10,4.20,3.96,3.96,0.00,0.00
50,2986,0.00,15.76,0,3.10,4.20,3.96,3.96,0.00,0.00
50,546,0.00,15.76,0,3.10,4.20,3.96,3.96,0.00,0.00
25,3746,0.00,15.76,0,3.10,4.20,3.96,3.96,0.00,0.00
25,3337,0.00,15.76,0,3.10,4.20,3.96,3.96,0.00,0.00
25,3015,0.00,15.76,0,3.10,4.20,3.96,3.96,0.00,0.00
0,96,0.00,15.76,0,3.10,4.20,3.96,3.96,0.00,0.00
0,-12,0.00,15.76,0,3.10,4.20,3.96,3.96,0.00,0.00
0,-14,0.00,15.76,0,3.10,4.20,3.96,3.96,0.00,0.00
End of Test Pass
The solution to the problem was to replace the SD card with a faster one. Once I did that the data logged as it should. Thanks Patrick for the suggestion.

RFID (SoftwareSerial) influences/breaks connection with SD (SPI)

I'm creating a RFID logger with Arduino. I connected a RFID scanner, RTC module and a SD card reader. All parts are working fine together but when i started combining different sketches a problem occured.
Reading files and writing to files on the SD card is no problem as long as i don't scan a RFID card. When input is received from the RFID scanner it is no longer possible to read or write to the sd card. The connection seems to be "disconnected" as soon as RFID input is received.
I tried using different pins for the RFID scanner, another sequence of initializing in the setup but it doesn't make a difference.
Is this a limitation of the Arduino or am I doing something wrong?
I'm using a ATS125KRW RFID shield and a Catalex MicroSD card adpater in combination with a Arduino Mega.
// SD
#include <SD.h>
File myFile;
char idArray[100][11];
char nameArray[100][11];
// RTC
#include <Wire.h>
#include "RTClib.h"
RTC_DS1307 rtc;
// RFID
#include <SoftwareSerial.h>
SoftwareSerial rfid = SoftwareSerial(A8 , A9); //(RX,TX)
String cardID; //string to store card id
char c;
char cardArray[11];
int incomingByte = 0; // for incoming serial data
String rfidInput;
boolean logtosd;
void setup()
{
Serial.begin(9600);
initializeRFID();
initializeSD();
initializeRTC();
readfromSD();
}
void loop()
{
while(rfid.available()>0)
{
c = rfid.read();
rfidInput += c;
}
if(rfidInput.length() >=12)
{
Serial.print("SCanned: ");
Serial.println(rfidInput);
//writetoSD(rfidInput);
writetoSD("kaart");
rfidInput = "";
}
while(Serial.available()>0)
{
c = Serial.read();
cardID += c;
}
if(cardID.length() >= 2)
{
writetoSD(cardID);
cardID = "";
}
}
void initializeSD()
{
// GND en VCC aansluiting via pin 48 en 49
pinMode(48, OUTPUT); // set pin to output
digitalWrite(48, LOW); // GND pin dus LOW
pinMode(49, OUTPUT); // set pin to output
digitalWrite(49, HIGH); // VCC pin dus HIGH
pinMode(53, OUTPUT);
if (!SD.begin(53))
{
Serial.println("SD initialization failed");
return;
}
Serial.println("SD initialized");
}
void readfromSD()
{
//open the file for reading:
myFile = SD.open("db.txt");
if (myFile)
{
char line[25]; //Array to store entire line
int linenumber = 0;
int arrayPlace = 0;
while (myFile.available())
{
char ch = myFile.read();
if(ch != '\n')
{
line[arrayPlace] = ch;
arrayPlace ++;
}
else
{
char id[11];
char name[11];
//get ID from entire line
for(int x = 0; x <= 10 ; x++)
{
id[x] = line[x];
}
//Get NAME from entire line
for(int x = 11; x <= 19 ; x++)
{
if (line[x] != ';')
{
name[x-11] = line[x];
}
else
{
// NULL TERMINATE THE ARRAY
name[x-11] = '\0';
//STOP
x = 20;
}
}
// save name to nameArray
for(int x = 0; x <= 11 ; x++)
{
nameArray[linenumber][x] = name[x];
}
// NULL TERMINATE THE ARRAY
id[10] = '\0';
// save id to idArray
for(int x = 0; x <= 11 ; x++)
{
idArray[linenumber][x] = id[x];
}
linenumber +=1;
arrayPlace = 0;
} //else
} //while
// close the file:
myFile.close();
}
else
{
// if the file didn't open, print an error:
Serial.println("error opening db.txt");
}
}
void writetoSD(String cardID)
{
//open file for writing
myFile = SD.open("test.txt", FILE_WRITE);
// if the file opened okay, write to it:
if (myFile)
{
Serial.println("Writing time to test.txt...");
DateTime now = rtc.now();
myFile.print(now.day(), DEC);
myFile.print('/');
myFile.print(now.month(), DEC);
myFile.print('/');
myFile.print(now.year(), DEC);
myFile.print(' ');
myFile.print(now.hour(), DEC);
myFile.print(':');
myFile.print(now.minute(), DEC);
myFile.print(':');
myFile.print(now.second(), DEC);
myFile.print('\t');
Serial.println("Writing string to test.txt...");
myFile.println(cardID);
// close the file:
myFile.flush();
Serial.println("done.");
}
else
{
// if the file didn't open, print an error:
Serial.println("error opening test.txt");
}
}
void initializeRTC()
{
// GND en VCC aansluiting via pin 18 en 19
pinMode(18, OUTPUT); // set pin to output
digitalWrite(18, LOW); // GND pin dus LOW
pinMode(19, OUTPUT); // set pin to output
digitalWrite(19, HIGH); // VCC pin dus HIGH
#ifdef AVR
Wire.begin();
#else
Wire1.begin(); // Shield I2C pins connect to alt I2C bus on Arduino Due
#endif
rtc.begin();
Serial.print("RTC Initialized: ");
DateTime now = rtc.now();
Serial.print(now.day(), DEC);
Serial.print('/');
Serial.print(now.month(), DEC);
Serial.print('/');
Serial.print(now.year(), DEC);
Serial.print(' ');
Serial.print(now.hour(), DEC);
Serial.print(':');
Serial.print(now.minute(), DEC);
Serial.print(':');
Serial.print(now.second(), DEC);
Serial.println();
}
void initializeRFID()
{
rfid.begin(9600);
Serial.println("RFID initialized");
}
I think you are running out of RAM ,i have done a lot of data logging on SD card with Arduino and its a very resources taking job for the minial 2kb ram on the UNO (assuming u using UNO).
Try using MemoryFree() library before every place you see there might be problem to see if you are running outta memory?

Resources