Arduino Due maximum interrupt frequency - c++

I am trying to implement my own SPI communication from FPGA to Arduino, in which my FPGA serve as MASTER and generate Chip enable and clock for communication. FPGA transmit data at its rising edge and receive data at its falling edge my FPGA code works properly.
In Arduino side I capture this master clock on interrupts and receive data at its rising edge and transmit at its falling edge but communication does not work properly if I increase clock speed from 10 KHz.
According to my understanding, Arduino Due works at 84 MHz and handling 1 MHz interrupts is not a big problem. Can you tell me how I can handle this high-speed clock with an Arduino Due?
Arduino code below:
void ISR1();
// this constant won't change
const int S_CLK = 19; // slow clock in this case FPGA is master
const int MOSI_C = 51; // Master out slave in in this case arduino
//receive data from FPGA
const int MISO_C = 50; // Master in slave out in this case arduino
//transmit data from FPGA
const int SS_C = 53; // the pin that the pushbutton is attached to
const int TRANS_INDEX = 32; //index that is used to transmit data in this
cas 32 bits are transmitted
const int REC_INDEX = 48;
#define CLK_MAIN 84000000UL
//Variables will change
int ss_check = 0; //used for reading of slave select
int mosi_data[REC_INDEX + 2]; //delcare receiving data array length
int count = 0; //used for convertion of bits to bytes
int index_r_stat = 0; //give us a value of status that
how much bits are received
int flag = 0; //used for stop reading s
int miso_out[TRANS_INDEX] = {
1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0
};
int miso_index = 0; //used for above array
int last_clk_state = 1; //used for the detection of rising and
falling edge
int check_clk;
void setup() {
// initialize the button pin as a input
pinMode(S_CLK , INPUT);
pinMode(MOSI_C , INPUT);
pinMode(MISO_C , OUTPUT);
pinMode(SS_C , INPUT);
// initialize serial communication
Serial.begin(9600);
}
void loop() {
// read the pushbutton input pin
ss_check = digitalRead(SS_C);
//Serial.println(ss_check);
//WAIT until slave select is not read
if (ss_check == 0) {
//attach interrupt so that data is
attachInterrupt(digitalPinToInterrupt(S_CLK), ISR1, CHANGE);
}
if ((index_r_stat == (REC_INDEX + 1)) && (flag == 0)) {
for (int i = 1; i < (REC_INDEX + 1); i = i + 1) {
Serial.print(mosi_data[i]);
flag = 1;
if (count < 7) {
count = count + 1;
} else {
count = 0;
Serial.println();
}
}
}
}
void ISR1() {
if ((last_clk_state == 1) && (digitalRead(S_CLK) == 0)) {
check_clk = 0;
//this code is used to transmit data to FPGA
if (miso_index < TRANS_INDEX - 1) {
digitalWrite(MISO_C, miso_out[miso_index]);
miso_index = miso_index + 1;
} else {
miso_index = miso_index;
}
} else {
check_clk = 1;
//this code is used for reading data from FPGA
if (index_r_stat < (REC_INDEX + 1)) {
mosi_data[index_r_stat] = digitalRead( MOSI_C);
index_r_stat = index_r_stat + 1;
} else {
detachInterrupt(S_CLK);
index_r_stat = index_r_stat;
}
}
last_clk_state = digitalRead(S_CLK);
}

Related

PWM sine wave using arduino and H bridge

I'm trying to provide a sinusoidal wave using PWM modulation.
my circuit is comprised of the following:
Arduino Uno
H bridge - controls the direction (pins 4,5) and the PWM voltage (PWM pin 6)
Solenoid motor - the sine output should be fed to the motor
I saw some guides online, but most of them use Sinewave tables and low-level code that I couldn't quite comprehend, so I have decided to give it a try with some more trivial code as followed:
const int DIR1_PIN = 4;
const int DIR2_PIN = 5;
const int PWM_PIN = 6;
const int LED_PIN = 9;
const int numSamples = 20;
const int sampleFreq = 2000;
const float pi = 3.1415;
float f = 1; // signal frequency
float T = 1/f;
float dt = T/numSamples;
int sineSignal[numSamples]; // sine values would be added here
int dir1Array[numSamples]; // 11....100....0 indicates direction
int dir2Array[numSamples]; // 00....011....1 indicates other direction
void setup()
{
pinMode(LED_PIN, OUTPUT); // the led is just an indicator to what the output is
pinMode(DIR1_PIN, OUTPUT);
pinMode(DIR2_PIN, OUTPUT);
pinMode(PWM_PIN, OUTPUT);
for (int n = 0; n < numSamples; n++)
{
sineSignal[n] = abs((int) (255 * (sin(2 * pi * f * n * dt))));
if (n < numSamples / 2)
{
dir1Array[n] = HIGH;
dir2Array[n] = LOW;
}
else
{
dir1Array[n] = LOW;
dir2Array[n] = HIGH;
}
}
}
void loop()
{
for (int n = 0; n < numSamples; n++)
{
analogWrite(LED_PIN, sineSignal[n]);
analogWrite(PWM_PIN, sineSignal[n]);
digitalWrite(DIR1_PIN, dir1Array[n]);
digitalWrite(DIR2_PIN, dir2Array[n]);
delay(sampleFreq); // not quite sure how the delay affects the frequency f
}
}
long story short, this code does not allow me to control the frequency f (getting the same output for different values of f)
any Idea on how to generate such output for varying f? how should one set up a delay call, if even?
Thank you!

Code for reading input from multiple analog pins on Arduino will not show values

This code that I tried to build myself does not give the output I want.
I'm hoping for an output lik "125, 567, 654, 332, 222, 123".
(6 values, separated by ", ")
If I run another program, I get the values, so there is someting wrong or missing in my code for sure.
#define cellPin A0
#define cellPin A1
#define cellPin A2
#define cellPin A3
#define cellPin A4
#define cellPin A5
float counts = 0;
float const pins = 6; // No of pins from 0 to 5
int timer = 1000;
int stored_pin_values[5];
int average_reads = 20;
void setup() {
Serial.begin(9600); // setup serial
}
void loop() {
for (int x = 0; x < pins; x++) { // counter for each pin, from 0 to 5
for (int i = 0; i < average_reads; i++) { // counter for each reading of the selected pin
if (i == 0) { analogRead("cellPin A"[i]); } // Read pin but do not use first reading
if (i != 0) { counts = analogRead("cellPin A"[i]) + counts; } // read the input pin and add to sum of counts
}
stored_pin_values[x] = counts / (average_reads - 1); // Calc. average of pin. -1 cus we did not use the first reading
counts = 0;
}
for (int y = 0; y < pins; y++) { // Counter for printing average value of each pin
if (y == pins - 1) { Serial.println(stored_pin_values[y]); } //on last pos. print "ln"
else {
Serial.print(stored_pin_values[y]); // print "average pinvalue" separated by ", "
Serial.print(", ");
}
}
delay(timer);
}
you have defined multiple values for cellPin.
#define cellPin A0
#define cellPin A1
#define cellPin A2
#define cellPin A3
#define cellPin A4
#define cellPin A5
I suggest to use a various name like #define cellPin0 A0 #define cellPin1 A1 ...
For second you call analogRead("cellPin A"[i]), passing string with illegal operator for argument: the right method is analogRead(int) -> int.
I write a little sketch for inspiring you:
int analogPins[6]={A0,A1,A2,A3,A4,A5}, //pins
analogValues[6]={0,0,0,0,0,0}; //stores the value of analog read
void setup(){
Serial.begin(9600); //serial communication with baud rate of 9600b/s
}
void loop(){
for(int i=0;i<6;i++){
analogValues[i]=analogRead(analogPins[i]);
}
}
I hope that can help you. Good luck!
Working code after change (note: changed to 5 pin reading instead of 6):
int analogPins[5]={A0,A1,A2,A3,A4}, //pins
analogValues[5]={0,0,0,0,0}; //stores the value of analog read
float counts = 0;
float const pins = 5; // No of pins from 0 to 4
int timer = 1000;
int stored_pin_values[5];
int average_reads = 100;
void setup() {
Serial.begin(9600); // setup serial
}
void loop() {
for (int x = 0; x < pins; x++) { // counter for each pin, from 0 to 4
for (int i = 0; i < average_reads; i++) { // counter for each reading of the selected pin
if (i == 0) { analogRead(analogPins[i]); } // Read pin but do not use first reading
if (i != 0) { counts = analogRead(analogPins[i]) + counts; } // read the input pin and add to sum of counts
}
stored_pin_values[x] = counts / (average_reads - 1); // Calc. average of pin. -1 cus we did not use the first reading
counts = 0;
}
for (int y = 0; y < pins; y++) { // Counter for printing average value of each pin
if (y == pins - 1) { Serial.println(stored_pin_values[y]); } //on last pos. print "ln"
else {
Serial.print(stored_pin_values[y]); // print "average pinvalue" separated by ", "
Serial.print(", ");
}
}
delay(timer);
}

Does arduino count++ has a limit and how to fix it?

I needed to make a meters counter for a work thing, so I decided to just Arduino for it. I found an old encoder, found/wrote a simple code and hacked it all together and encountered a unexpected problem.
For some reason my counter won't count past around 8 meters or 31991 encoder pulses. Once it reaches this 8m limit, the number turns negative and starts counting backwards like -7.9 > -7.8 (i.e. continues counting upward towards 0).
Then it reaches zero and again counts to 8...
This is very strange to me and my limited coding knowledge can't fix it.
Does anyone know how to fix this or what I could do to make it work?
#include <LiquidCrystal.h>
#define inputA_in 6
#define inputB_in 7
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
int inputA_V = 0;
int inputB_V = 0;
int inputA = 0;
int inputB = 0;
int counter = 0;
// smeni vrednost tuka pred run
int console_frequency_milliseconds = 200; /// edna sekunda
int aLastState = 0;
int bLastState = 0;
float meters = 0.0;
unsigned long lasttime = 0;
int move_positive = 0;
int move_negative = 0;
int maximum_input_digital_v = 300; //treba da citash od konzola i da gi setirash max i min
int minimum_input_digital_v = 0;
int logical_threshold_v = 150; //brojkive se random staveni
void setup() {
pinMode (inputA_in, INPUT);
pinMode (inputB_in, INPUT);
Serial.begin (9600);
lcd.begin(16, 2);
// Print a message to the LCD
lcd.print("Metraza [m]");
aLastState = inputA;
bLastState = inputB;
lasttime = 0;
}
void loop () {
inputA = digitalRead(inputA_in);
if (inputA != aLastState) {
if (digitalRead(inputB_in) != inputA) {
counter ++;
aLastState = inputA;
} else {
counter --;
aLastState = inputA;
}
}
if (millis() - console_frequency_milliseconds > lasttime)//Detect once every 150ms
{
meters = 0.50014 * counter / 2000;
Serial.print("Position: ");
Serial.println(meters);
lasttime = millis();
lcd.setCursor(0, 1);
//Print a message to second line of LCD
lcd.print(meters);
}
}
Your counter is a simple int,
int counter = 0;
It seems that on your system they are only 16bit wide (with a maximum value of 32767), not surprising.
Use
long int counter = 0;
to get wider variables.
You might also want to change the calculation from
meters = 0.50014 * counter / 2000;
to
meters = 0.50014 * counter / 2000.0;
to avoid losing precision and range. Even with an int that would extend your range from 31991 encoder pulses to 32757 encoder pulses; and analog for the wider range.
You might also like to try changing the counter to an unsigned int or unsigned long int. I did not analyse your whole code, but I think you do not have anything which relies on representation of negative numbers. So you probably could double the range again. But no guarantees, subject to testing.

How can I stop music with a push button?

I would like to know how to stop music with a push button (to stop it exactly at the moment you press the button). Because at the moment my code does what I want(stop the music and turn on a light when I press the press button, but it waits untill the end of the song to stop.
There is my code:
int buttonState = 0;
int speakerOut = 10;
int buttonPin= 7;
int frequency = 500;
int ledPin = 13;
int length = 17; // the number of notes
char notes[] = "gcefgcefgcefgcefga "; // a space represents a rest
//int beats[] = {2,2,1,1,2,2,1,1,2,2,1,1,2,2,1,1};
//int tempo = 250;
int DEBUG = 1;
#define c 3830
#define d 3400
#define e 3038
#define f 2864
#define g 2550
#define a 2272
#define b 2028
#define C 1912
#define R 0
void setup() {
// put your setup code here, to run once:
pinMode(ledPin, OUTPUT);
pinMode(buttonPin,INPUT);
pinMode(speakerOut, OUTPUT);
if (DEBUG) {
Serial.begin(9600); // Set serial out if we want debugging
}
}
// MELODY and TIMING =======================================
// melody[] is an array of notes, accompanied by beats[],
// which sets each note's relative length (higher #, longer note)
int melody[] = { C, b, g, C, b, e, R, C, c, g, a, C };
int beats[] = { 16, 16, 16, 8, 8, 16, 32, 16, 16, 16, 8, 8 };
int MAX_COUNT = sizeof(melody) / 2; // Melody length, for looping.
// Set overall tempo
long tempo = 10000;
// Set length of pause between notes
int pause = 1000;
// Loop variable to increase Rest length
int rest_count = 100; //<-BLETCHEROUS HACK; See NOTES
// Initialize core variables
int tone_ = 0;
int beat = 0;
long duration = 0;
// PLAY TONE ==============================================
// Pulse the speaker to play a tone for a particular duration
void playTone() {
long elapsed_time = 0;
if (tone_ > 0) { // if this isn't a Rest beat, while the tone has
// played less long than 'duration', pulse speaker HIGH and LOW
while (elapsed_time < duration) {
digitalWrite(speakerOut,HIGH);
delayMicroseconds(tone_ / 2);
// DOWN
digitalWrite(speakerOut, LOW);
delayMicroseconds(tone_ / 2);
// Keep track of how long we pulsed
elapsed_time += (tone_);
}
}
else { // Rest beat; loop times delay
for (int j = 0; j < rest_count; j++) { // See NOTE on rest_count
delayMicroseconds(duration);
}
}
}
void loop() {
// put your main code here, to run repeatedly:
buttonState = digitalRead(buttonPin);
if (buttonState==HIGH){
digitalWrite(ledPin, HIGH);
noTone(speakerOut);
}else {
digitalWrite(ledPin, LOW);
digitalWrite(speakerOut,HIGH);
for (int i=0; i<MAX_COUNT; i++) {
tone_ = melody[i];
beat = beats[i];
duration = beat * tempo; // Set up timing
playTone();
// A pause between notes...
delayMicroseconds(pause);
}
}
}
You have 2 options, before playTone() check button and, if pressed, end the for loop.
for (int i=0; i<MAX_COUNT; i++) {
tone_ = melody[i];
beat = beats[i];
duration = beat * tempo; // Set up timing
if (digitalRead(buttonPin)==LOW){
playTone();
} else {
break; //End for loop
}
// A pause between notes...
delayMicroseconds(pause);
}
Or the same but using void loop() as a for loop. A global variable, count between 0 and MAX_COUNT and do the same check. If pressed, count=0; and if not, continue playing the next note. Now, I can't code write this but has no difficult.

Decode GPS NMEA code using arduino

I know this has been asked many times but I really can't find what I am really searching.
I am using an Arduino Uno and a GPS Shield that shows GPS data through serial.
Here is the code I am uploading to my Arduino to interface the GPS Shield:
void loop() // run over and over
{
while(!(mySerial.available())){}
Serial.write(mySerial.read());
}
That is just the code. Nevertheless, as it continuously loops, on a Serial Monitor, it also output GPS data every second.
Here is its output every second:
$GPGGA,013856.000,000.9090,N,9090.90,E,1,09,1.1,316.97,M,0.00,M,,*66
$GPGSA,A,3,07,08,11,1ÿ3,16,19,23,27,42,,,,2.8,1.1,2.5*3F
$GPRMC,013856.000,A,000.9090,N,9090.90,E,0.0,038.1,310814,,,A*62
$GPGSV,ÿ3,1,12,16,26,059,33,27,33,025,44,08,30,330,32,07,31,326,34*7A
$GPGSV,3,2,12,19,58,354,31,01,33,186,18,23,32,221,24,11,5ÿ9,198,31*70
$GPGSV,3,3,12,42,60,129,32,13,38,253,27,32,06,161,,31,01,140,*7E
As it updates every second, the coordinates changes to minimal, which means the GPS Shield is working.
The problem here is, I wanted to parse the GPS data, especially on the GPGGA line only, and ignore the other lines. I would like to parse the Status, Latitude, N/S Indicator, Longitude, and E/W Indicator.
I have searched for the NMEA Library (http://nmea.sourceforge.net/), but I have no idea how to use it.
Can someone please help me here? Thank you.
NMEA data is in a GPS-style (ddmm.ssss) format, Google wants it in Decimal Style (dd.mmssss), there is a coversion function at the bottom of the code for this step.
I wrote this because I don't like the large, complicated libraries to do simple little things, especially when I am trying to figure out how it works.
This parses the GLL sentence, but you can change the sentence it's looking for and rearrange the sections if needed.
String ReadString;
void setup() {
Serial.begin(9600); //Arduino serial monitor thru USB cable
Serial1.begin(9600); // Serial1 port connected to GPS
}
void loop() {
ReadString=Serial1.readStringUntil(13); //NMEA data ends with 'return' character, which is ascii(13)
ReadString.trim(); // they say NMEA data starts with "$", but the Arduino doesn't think so.
// Serial.println(ReadString); //All the raw sentences will be sent to monitor, if you want them, maybe to see the labels and data order.
//Start Parsing by finding data, put it in a string of character array, then removing it, leaving the rest of thes sentence for the next 'find'
if (ReadString.startsWith("$GPGLL")) { //I picked this sentence, you can pick any of the other labels and rearrange/add sections as needed.
Serial.println(ReadString); // display raw GLL data in Serial Monitor
// mine looks like this: "$GPGLL,4053.16598,N,10458.93997,E,224431.00,A,D*7D"
//This section gets repeated for each delimeted bit of data by looking for the commas
//Find Lattitude is first in GLL sentence, other senetences have data in different order
int Pos=ReadString.indexOf(','); //look for comma delimetrer
ReadString.remove(0, Pos+1); // Remove Pos+1 characters starting at index=0, this one strips off "$GPGLL" in my sentence
Pos=ReadString.indexOf(','); //looks for next comma delimetrer, which is now the first comma because I removed the first segment
char Lat[Pos]; //declare character array Lat with a size of the dbit of data
for (int i=0; i <= Pos-1; i++){ // load charcters into array
Lat[i]=ReadString.charAt(i);
}
Serial.print(Lat); // display raw latitude data in Serial Monitor, I'll use Lat again in a few lines for converting
//repeating with a different char array variable
//Get Lattitude North or South
ReadString.remove(0, Pos+1);
Pos=ReadString.indexOf(',');
char LatSide[Pos]; //declare different variable name
for (int i=0; i <= Pos-1; i++){
LatSide[i]=ReadString.charAt(i); //fill the array
Serial.println(LatSide[i]); //display N or S
}
//convert the variable array Lat to degrees Google can use
float LatAsFloat = atof (Lat); //atof converts the char array to a float type
float LatInDeg;
if(LatSide[0]==char(78)) { //char(69) is decimal for the letter "N" in ascii chart
LatInDeg= ConvertData(LatAsFloat); //call the conversion funcion (see below)
}
if(LatSide[0]==char(83)) { //char(69) is decimal for the letter "S" in ascii chart
LatInDeg= -( ConvertData(LatAsFloat)); //call the conversion funcion (see below)
}
Serial.println(LatInDeg,15); //display value Google can use in Serial Monitor, set decimal point value high
//repeating with a different char array variable
//Get Longitude
ReadString.remove(0, Pos+1);
Pos=ReadString.indexOf(',');
char Longit[Pos]; //declare different variable name
for (int i=0; i <= Pos-1; i++){
Longit[i]=ReadString.charAt(i); //fill the array
}
Serial.print(Longit); //display raw longitude data in Serial Monitor
//repeating with a different char array variable
//Get Longitude East or West
ReadString.remove(0, Pos+1);
Pos=ReadString.indexOf(',');
char LongitSide[Pos]; //declare different variable name
for (int i=0; i <= Pos-1; i++){
LongitSide[i]=ReadString.charAt(i); //fill the array
Serial.println(LongitSide[i]); //display raw longitude data in Serial Monitor
}
//convert to degrees Google can use
float LongitAsFloat = atof (Longit); //atof converts the char array to a float type
float LongInDeg;
if(LongitSide[0]==char(69)) { //char(69) is decimal for the letter "E" in ascii chart
LongInDeg=ConvertData(LongitAsFloat); //call the conversion funcion (see below
}
if(LongitSide[0]==char(87)) { //char(87) is decimal for the letter "W" in ascii chart
LongInDeg=-(ConvertData(LongitAsFloat)); //call the conversion funcion (see below
}
Serial.println(LongInDeg,15); //display value Google can use in Serial Monitor, set decimal point value high
//repeating with a different char array variable
//Get TimeStamp - GMT
ReadString.remove(0, Pos+1);
Pos=ReadString.indexOf(',');
char TimeStamp[Pos]; //declare different variable name
for (int i=0; i <= Pos-1; i++){
TimeStamp[i]=ReadString.charAt(i); //fill the array
}
Serial.print(TimeStamp); //display raw longitude data in Serial Monitor, GMT
Serial.println("");
}
}
//Conversion function
float ConvertData(float RawDegrees)
{
float RawAsFloat = RawDegrees;
int firstdigits = ((int)RawAsFloat)/100; // Get the first digits by turning f into an integer, then doing an integer divide by 100;
float nexttwodigits = RawAsFloat - (float)(firstdigits*100);
float Converted = (float)(firstdigits + nexttwodigits/60.0);
return Converted;
}
I wrote this decent code, and it works up to two decimal places.
Code:
String gpsData;
String LATval = "######";
String LNGval = "######";
char inChar;
String gpsData;
String latt;
String la;
String lonn;
String lo;
float lattt;
float lonnn;
int latDeg;
int lonDeg;
float latMin;
float lonMin;
float latttt;
float lonnnn;
String sGPRMC;
void setup() {
Serial.begin(9600);
}
void loop() {
while (Serial.available()) {
inChar = Serial.read();
gpsData += inChar;
if (inChar == '$') {
gpsData = Serial.readStringUntil('\n');
break;
}
}
Serial.println(gpsData);
sGPRMC = gpsData.substring(0, 5);
if (sGPRMC == "GPRMC") {
Serial.flush();
latt = gpsData.substring(18, 28);
la = gpsData.substring(29, 30);
lonn = gpsData.substring(31, 42);
lo = gpsData.substring(43, 44);
Serial.print("latt:");
Serial.println(latt);
Serial.print("la:");
Serial.println(la);
Serial.print("lonn:");
Serial.println(lonn);
Serial.print("lo:");
Serial.println(lo);
lattt = latt.toFloat();
lonnn = lonn.toFloat();
Serial.print("lattt:");
Serial.println(lattt);
Serial.print("lonnn:");
Serial.println(lonnn);
if (la == "N" and lo == "E") {
latDeg = float(int(lattt / 100));
latMin = float(lattt - (latDeg * 100));
latMin = latMin / 60;
lonDeg = float(int(lonnn / 100));
lonMin = float(lonnn - (lonDeg * 100));
lonMin = lonMin / 60;
latttt = latDeg + latMin;
lonnnn = lonDeg + lonMin;
LATval = String(latttt);
LNGval = String(lonnnn);
Serial.print("latDeg:");
Serial.println(latDeg);
Serial.print("latMin:");
Serial.println(latMin);
Serial.print("lonDeg:");
Serial.println(lonDeg);
Serial.print("lonMin:");
Serial.println(lonMin);
Serial.print("LATval:");
Serial.println(LATval);
Serial.print("LNGval:");
Serial.println(LNGval);
}
}
}
I have searched the Internet, and the best answer would be using the "TinyGPS++" library for Arduino. Almost all GPS-related codes are already included on the Library.
You can use TinyGPS to parse the NMEA strings. If you are interested in only 1 sentence. You can write a custom parser as below for that sentence only.
int handle_byte(int byteGPS) {
buf[counter1] = byteGPS;
//Serial.print((char)byteGPS);
counter1++;
if (counter1 == 300) {
return 0;
}
if (byteGPS == ',') {
counter2++;
offsets[counter2] = counter1;
if (counter2 == 13) {
return 0;
} } if (byteGPS == '*') {
offsets[12] = counter1; }
// Check if we got a <LF>, which indicates the end of line if (byteGPS == 10) {
// Check that we got 12 pieces, and that the first piece is 6 characters
if (counter2 != 12 || (get_size(0) != 6)) {
return 0;
}
// Check that we received $GPRMC
// CMD buffer contains $GPRMC
for (int j=0; j<6; j++) {
if (buf[j] != cmd[j]) {
return 0;
}
}
// Check that time is well formed
if (get_size(1) != 10) {
return 0;
}
// Check that date is well formed
if (get_size(9) != 6) {
return 0;
}
SeeedOled.setTextXY(7,0);
for (int j=0; j<6; j++) {
SeeedOled.putChar(*(buf+offsets[1]+j));
}
SeeedOled.setTextXY(7,7);
for (int j=0; j<6; j++) {
SeeedOled.putChar(*(buf+offsets[9]+j));
}
// TODO: compute and validate checksum
// TODO: handle timezone offset
return 0; }
return 1; }
Try this which can help you
#include <SoftwareSerial.h>
#include <TinyGPS.h>
TinyGPS gps;
SoftwareSerial ss(3,4);
static void smartdelay(unsigned long ms);
static void print_float(float val, float invalid, int len, int prec);
static void print_int(unsigned long val, unsigned long invalid, int len);
static void print_date(TinyGPS &gps);
static void print_str(const char *str, int len);
void setup()
{
Serial.begin(9600);
ss.begin(9600);
}
void loop()
{
float flat, flon;
unsigned short sentences = 0, failed = 0;
gps.f_get_position(&flat, &flon);
Serial.print("LATITUDE: ");
print_float(flat, TinyGPS::GPS_INVALID_F_ANGLE, 10, 6);
Serial.println(" ");
Serial.print("LONGITUDE: ");
print_float(flon, TinyGPS::GPS_INVALID_F_ANGLE, 11, 6);
Serial.println(" ");
Serial.print("altitude: ");
print_float(gps.f_altitude(), TinyGPS::GPS_INVALID_F_ALTITUDE, 7, 2);
Serial.println(" ");
Serial.print("COURSE:");
print_float(gps.f_course(), TinyGPS::GPS_INVALID_F_ANGLE, 7, 2);
Serial.println("");
Serial.print("DIRECTION: ");
int d;
print_str(gps.f_course() == TinyGPS::GPS_INVALID_F_ANGLE ? "*** " : TinyGPS::cardinal(gps.f_course()), 6);
d=gps.f_course();
Serial.println();
Serial.println();
smartdelay(1000);
}
static void smartdelay(unsigned long ms)
{
unsigned long start = millis();
do
{
while (ss.available())
gps.encode(ss.read());
} while (millis() - start < ms);
}
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);
}
static void print_int(unsigned long val, unsigned long invalid, int len)
{
char sz[32];
if (val == invalid)
strcpy(sz, "*******");
else
sprintf(sz, "%ld", val);
sz[len] = 0;
for (int i=strlen(sz); i<len; ++i)
sz[i] = ' ';
if (len > 0)
sz[len-1] = ' ';
Serial.print(sz);
smartdelay(0);
}
static void print_str(const char *str, int len)
{
int slen = strlen(str);
for (int i=0; i<len; ++i)
Serial.print(i<slen ? str[i] : ' ');
smartdelay(0);
}