I am trying to write an Application with C++ Builder which should display for example the temperature and humidity of a measurement from the Arduino. Arduino and my Application are connected via TComPort. I am using a Baudrate of 115200.
VCL Code:
AnsiString temp, hum;
ComPort1->ReadStr(temp, 5);
RichEdit1->Text = temp;
ComPort1->ReadStr(hum, 5);
RichEdit3->Text = hum;
Arduino Code:
DHT dht(10, DHT11);
void setup(void)
{
dht.begin();
Serial.begin(115200);
}
void loop(void)
{
// Measure the humidity & temperature
float h = dht.readHumidity();
float t = dht.readTemperature();
// Transform to String
String temp = String( t );
String hum = String( h );
delay(10);
Serial.print(temp);
Serial.print(hum);
delay(5000);
}
When I start my Application (VCL with C++ Builder) and connect to the Arduino every 5 seconds, the values should be refreshed by new values. Most of the time the 2 values are correct and it displays like it should for example
Temperature: 24:00
Humidity: 55.00
But for some reason every now and then it displays something like this:
Temperature: .0051
Humditiy: .00
or some other weird values. 5 seconds later the values are correct again. This happens every 20-30 seconds 1 time and i dont know why this keeps happening.
In the TComPort.OnRxChar event, there is a Count parameter that tells you how many bytes are available. Don't read more than that. Buffer the bytes to the side, and then read only complete values from that buffer.
For example:
private:
AnsiString ComPortBuffer;
void __fastcall TMyForm::ComPort1RXChar(TObject *Sender, int Count)
{
AnsiString s;
int len = ComPort1->ReadStr(s, 5);
if (len > 0)
{
if (len < 5)
s.SetLength(len);
ComPortBuffer += s;
}
while (ComPortBuffer.Length() >= 10)
{
AnsiString temp = ComPortBuffer.SubString(1, 5);
AnsiString hum = ComPortBuffer.SubString(6, 5);
ComPortBuffer.Delete(1, 10);
// use temp and hum as needed...
RichEdit1->Text = temp;
RichEdit3->Text = hum;
}
}
Related
I have started a small project to hopefully replace RPis running a Java library with Arduinos.
(I am normally working with Java, so not as familiar with C)
There are multiple temp sensors connected to the board. I read the values and want to store them with a reference to the sensor address. When a value changes, an update of all the sensors with their address and the temperatures is send to the server (hence I need the store to compare the values every 10 seconds).
I am trying to use the HashMap from Arduino Playground, as on a first look it seemed to do what I need and seems lightweight.
However, when reading the address of the temp sensor from a variable from the HashMap it doesn't return the right one (when there is some data pre-set in the hashmap):
int strLen = sAddress.length();
char *cAddress = (char *)malloc(strLen+1);
sAddress.toCharArray(cAddress, strLen+1);
byte position = sensorHashMap.getIndexOf(cAddress);
However, if I replace the *cAddress with:
char *cAddress = "28aae25501412c";
it does find it. So what am I doing wrong?
My approach to store the temp values with the address as a reference might not be the best, and it seems that the code crashes later on when trying to update the value but I haven't gone down that far yet. If there is a better solution than I am very open to some suggestions off course.
The full code below:
#include <HashMap.h>
#include <OneWire.h>
#include <ESP8266WiFi.h>
#include <DS18B20.h>
char wifiSSID[] = "xxxx";
char wifiPassword[] = "xxxx";
unsigned long lastTempCheck = 0;
const byte HASH_SIZE = 10; // Max 10 (temp) sensors etc
HashType<char*, float> hashRawArray[HASH_SIZE];
HashMap<char*, float> sensorHashMap = HashMap<char*, float>( hashRawArray , HASH_SIZE );
int sensorsRegistered = 1;
WiFiClient client;
DS18B20 ds(5); // Is D1
void setup()
{
Serial.begin(115200);
Serial.println();
WiFi.begin(wifiSSID, wifiPassword);
Serial.print("Connecting");
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}
Serial.println("---");
Serial.println("Connected to wifi");
Serial.print("Connected, IP address: ");
Serial.println(WiFi.localIP());
Serial.println("Setup completed, ready to run...");
// Test data
sensorHashMap[0]("name", 18);
sensorHashMap[1]("test", 200);
sensorHashMap[2]("qwer", 1234);
sensorHashMap[3]("28fffa6f51164ae", 123);
sensorHashMap[4]("28aae25501412c", 456);
}
void loop() {
// Duty cycle of the application
delay(100);
if ((millis() < lastTempCheck) || (millis() - lastTempCheck > 1000 * 10)) {
// Verifying the HashMap works with the pre-set values.
Serial.print("Checking pre-set values: ");
Serial.println( sensorHashMap.getIndexOf("28fffa6f51164ae"), DEC );
Serial.print("Checking sensor value: ");
Serial.println( sensorHashMap.getValueOf("28fffa6f51164ae") );
while (ds.selectNext()) {
float temp = ds.getTempC();
uint8_t address[8];
ds.getAddress(address);
String sAddress = "";
for (uint8_t i = 0; i < 8; i++) {
sAddress += String(address[i], HEX);
}
int strLen = sAddress.length();
char *cAddress = (char *)malloc(strLen+1);
sAddress.toCharArray(cAddress, strLen+1);
//char *cAddress = "28aae25501412c";
byte position = sensorHashMap.getIndexOf(cAddress);
Serial.print("Position: ");
Serial.println( position);
Serial.println( sensorHashMap.getIndexOf(cAddress), DEC );
if (position < HASH_SIZE) {
Serial.print("Updating sensor value, currently: ");
Serial.println( sensorHashMap.getValueOf(cAddress));
sensorHashMap[position](cAddress, temp); //ds.getTempC()
} else {
Serial.print("Creating sensor value, id is going to be ");
Serial.println(sensorsRegistered);
sensorHashMap[sensorsRegistered](cAddress, temp);
sensorsRegistered++;
}
free(address);
}
lastTempCheck = millis();
}
}
Appreciate your time.
I am trying to convert "String" read from serial port in serialEvent() of Arduino IDE to integer values with exact representation.
For eg, if String myString = 200 then int myInt should be 200.
I have been somewhat successful but unable to convert String to exact int representation beyond 255.
Solutions I have tried:
1) used .toInt() function in Arduino.
2) used "atoi" and "atol" functions.
3) Serial.parseInt() in loop().
All of these methods start recounting from 0 after every 255 values.
I can't use parseInt since it only works inside loop(). My application requires to store variable value permanently until another value is given through port. For this Arduino Due's flash memory has been used.
The memory storing code seems to work only inside serialEvent().
Code snippet is as below:
#include <stdlib.h>
#include <DueFlashStorage.h>
DueFlashStorage memory;
String x = " ";
int x_size;
int threshold;
void setup(){
Serial.begin(115200);
}
void loop{
Serial.println(memory.read(0));
}
void serialEvent(){
while(Serial.available()){
x = Serial.readStringUntil('\n');
x_size = x.length();
char a[x_size+1];
x.toCharArray(a, x_size+1);
threshold = atoi(a);
memory.write(0, threshold);
}
}
1) Function .toInt() returns LONG and you want INT (I don't know why honestly but it is in documentation)... you need to cast it like this (tried on Arduino ATMEGA and it worked):
#include <stdlib.h>
String x = "1000";
int x_ = 0;
void setup() {
Serial.begin(9600);
}
void loop() {
x_ = (int) x.toInt();
Serial.println(x_);
delay(1000);
}
2) I’m not professional ... but serilEvent() is really old way of doing things and it isn't recommended to use it. You can do it "manually" in the loop() function.
You're only converting 1 character a time, that's why the limit is 255.
If you're not doing anything else, you could stay in a serial.read-loop until all characters are read. For example:
void loop() {
if(Serial.available()) {
byte count = 0;
char number[10]; // determine max size of array
bool wait = true;
while(wait) { // stay in this loop until newline is read
if(Serial.available()) {
number[count] = Serial.read();
if (number[count] == '\n') {
wait = false; // exit while loop
}
count++;
}
}
int threshold = atoi(number);
memory.write(0, threshold);
}
}
For the lack of a good function in Arduino IDE for char/String type to int type conversion (has a limit of 255), I wrote my own conversion code which seems to work perfectly.
int finalcount=0;
void setup(){
Serial.begin(115200);
}
void loop(){
if(Serial.available()) {
int count = 0;
char number[5]; // determine max size of array as 5
bool wait = true;
while(wait) { // stay in this loop until newline is read
if(Serial.available()) {
number[count] = Serial.read();
if (number[count] == '\n') {
finalcount = count; //max array size for integer; could be less than 5
wait = false; // exit while loop
}
count++;
}
}
int val[finalcount]; //array size determined for integer
int placeValue;
int finalval[finalcount];
int temp=0;
int threshold;
for(int i = 0; i<finalcount; i++){
val[i] = (int)number[i]-48; //convert each char to integer separately
placeValue = pow(10,(finalcount-1)-i); //calculate place value with a base of 10
finalval[i] = val[i]*placeValue; //update integers with their place value
temp += finalval[i] ; //add all integers
threshold = temp; //resulting number stored as threshold
}
Serial.println(threshold); //prints beyond 255 successfully !
}
}
I solved the problem using highByte and lowByte functions of Arduino. Works flawlessly.
#include <DueFlashStorage.h>
DueFlashStorage m;
byte a1,a2;
int val;
void setup() {
Serial.begin(115200); //start the serial communication
}
void loop()
{
if (Serial.available()>0)
{
val = Serial.parseInt(); //read the integer value from series
if(val>0){
a1 = highByte(val); //get the higher order or leftmost byte
a2 = lowByte(val); //get the lower order or rightmost byte
m.write(0,a1); //save in arduino due flash memory address 0
m.write(1,a2); //save in arduino due flash memory address 1
}
int myInteger;
myInteger = (m.read(0)*256)+m.read(1); //convert into the true integer value
Serial.println(myInteger);
}
I am trying to receive sensor data from Arduino and write the readings into a file using Processing IDE (using serial communication / USB).
After doing a large amount of tests, I am pretty sure it's the Processing side unable to process the data. Only the first few (< 100) "samples" are written successfully, after that Serial.available() always returns false.
I am sending two-byte chunks from Arduino, 57600 baud, default settings (8 bit, no parity, 1 stop bit).
Arduino code:
unsigned int data = 0;
unsigned char buf[2];
void setup() {
Serial.begin(57600);
}
void loop() {
data = analogRead(A0);
buf[0] = data & 0xFF; // low byte
buf[1] = data >> 8; // high byte
Serial.write(buf, 2);
Serial.flush();
delayMicroseconds(300);
}
Processing code:
import processing.serial.*;
Serial serialPort;
String serialData;
PrintWriter output;
int recordingTime = 1000; // how many miliseconds of data stream to record
byte[] dataBuffer = new byte[2]; // reserve memory for 2 bytes and initialize to 0 (java stuff)
int receivedBytes = 0;
void setup()
{
serialPort = new Serial(this, "/dev/ttyUSB0", 57600);
output = createWriter("serialData.txt");
}
void draw()
{
while(millis() < recordingTime) {
if (serialPort.available() > 0) {
receivedBytes = serialPort.readBytes(dataBuffer);
output.print("\n");
output.print("Received bytes: ");
output.print(receivedBytes);
output.print("\n");
output.println(binary(dataBuffer[0])); // low byte
output.println(binary(dataBuffer[1])); // high byte
output.println("");
}
else {
output.print("\n");
output.println("No data available");
}
}
output.flush();
output.close();
exit();
}
Output:
Received bytes: 2
11101001
00000011
Received bytes: 2
11101001
00000011
Received bytes: 2
11101001
00000011
...after some lines...
No data available
No data available
No data available
No data available
No data available
No data available
Why is this happening? Why is there "no data available" after few samples? If I watch the serial monitor output in Arduino IDE, it works fine.
I can read the serial data from Arduino using screen and using Python. Still cannot get it to work in Processing - only receiving few samples (17 exactly).
Screen command: $ screen <port name> <baud rate> (press ctrl+a and then shift+k to stop the program; add -L flag for logging to a file). Works as expected.
I managed to achieve the same results using Pyserial library in Python:
#
# log_serial.py
# Writes incoming serial data to file.
import time
import serial
# Edit this parameters =========================================================
serialPort = "/dev/ttyUSB0"
baudrate = 57600
recordTime = 1000 # milliseconds
# ==============================================================================
def millis():
"""
Returns current (wall-)time in milliseconds
"""
return int(round(time.time() * 1000))
ser = serial.Serial(serialPort, baudrate)
with open("output.txt", "w") as f:
startTime = millis()
f.write("Recording started at: ")
f.write(str(startTime))
f.write("\n")
while (millis() - startTime) <= recordTime:
inData = ser.read(2) # reads two bytes
inInt = int.from_bytes(inData, byteorder='little') # merges them into an integer
f.write(str(inInt))
f.write("\n")
f.write("Recording finished at: ")
f.write(str(millis()))
f.write("\n")
Still don't know why the Processing version can't handle it...
There was a bug (wrong while loop condition) in my first Processing code. Here is updated version, using Serial.read() rather than Serial.readBytes(buffer). Still doesn't solve my problem, only getting 17 samples:
import processing.serial.*;
Serial serialPort;
String serialData;
PrintWriter output;
int recordingTime = 5000; // how many miliseconds of data stream to record
void setup()
{
serialPort = new Serial(this, "/dev/ttyUSB0", 57600);
output = createWriter("serialData.txt");
}
void draw()
{
int startTime = millis();
while((millis() - startTime) <= recordingTime) {
if (serialPort.available() > 0) {
int b1 = serialPort.read();
int b2 = serialPort.read();
int value = (b2 << 8) + (b1 & 0xFF);
output.println(value);
}
}
output.flush();
output.close();
exit();
}
Please try to run this code and post the content of the written file afterwards:
import processing.serial.*;
Serial serialPort;
String serialData;
PrintWriter output;
int recordingTime = 5000; // how many miliseconds of data stream to record
void setup()
{
serialPort = new Serial(this, "/dev/ttyUSB0", 57600);
output = createWriter("serialData.txt");
}
void draw()
{
int startTime = millis();
while((millis() - startTime) <= recordingTime) {
if (serialPort.available() > 0) {
int b1 = serialPort.read();
int b2 = serialPort.read();
int value = (b2 << 8) + (b1 & 0xFF);
output.print(millis()); //to each received value there is written the actual millis()-value
output.print(",");
output.println(value);
}
}
output.flush();
output.close();
exit();
}
I have no problems with the Serial communication between Processing and my Arduino Uno/Mega using serialPort.read() instead of serialPort.readBytes(dataBuffer). Maybe this makes a difference...
Have you already tried to increase the variable recordingTime?
I am taking voltage signal from Analog Input (A0 pin) and current signal (in the form of voltage) from Analog input (A1 pin), converting it to digital and then processing it to get Vrms, Irms and phase data. Then i am storing it in a "dataString" and writing it onto SD card.
The problem i am facing is that somewhere in the floating point computation of the power factor I am doing something wrong due to which the answer is being "displayed as" 1.00 whereas at an angle of 4.97 (degrees) i should get cos(4.97) = 0.9962 (Picture attached)
Image1
Although the program is using the correct value i.e., 0.9962 in further computations ( that of real Power) but i want it to display the power factor correctly upto 4 points after decimal. Here is my program code
#include <SPI.h>
#include <SD.h>
#include <Wire.h>
#include "RTClib.h"
RTC_DS1307 RTC;
#include "DHT.h"
#define DHTPIN 8
#define DHTTYPE DHT21
DHT dht(DHTPIN, DHTTYPE);
#define count 100
const int analogInPin1 = A1;
const int analogInPin0 = A0;
const int chipSelect = 10;
void setup()
{
Serial.begin(115200);
Wire.begin();
RTC.begin();
if (! RTC.isrunning()) {
Serial.println("#RTC is NOT running!");
// following line sets the RTC to the date & time this sketch was compiled
// uncomment it & upload to set the time, date and start run the RTC!
// RTC.adjust(DateTime(__DATE__, __TIME__));
}
analogReference(DEFAULT);
Serial.println("#DHTxx test!");
dht.begin();
Serial.print("#Initializing SD card...");
// see if the card is present and can be initialized:
if (!SD.begin(chipSelect)) {
Serial.println("#Card failed, or not present");
// don't do anything more:
return;
}
Serial.println("#card initialized.");
Serial.println("#Date Time Vrms Irms Phase Power_factor Apparent_Power Real_Power Humidity Temperature");
}
void loop()
{
float sensorValue0[count];
float sumSensorValue0=0;
float meanSensorValue0=0;
float Vrms=0;
sumSensorValue0=0;
float sensorValue1[count];
float sumSensorValue1=0;
float meanSensorValue1=0;
float Irms=0;
int i=0;
sumSensorValue1=0;
DateTime now = RTC.now();
for(i=0;i<count;i++)
{
sensorValue1[i] = (analogRead(analogInPin1)*4.8)-3200; //4.8 mV (i.e. 0.0048 Volts) per unit.. Vref/1024.. here Vref = 5 V ....//3.220 V = Offset
sensorValue0[i] = (analogRead(analogInPin0)*4.8)-3200;
sensorValue1[i] = sensorValue1[i]*sensorValue1[i];
sensorValue0[i] = sensorValue0[i]*sensorValue0[i];
sumSensorValue1+= sensorValue1[i];
sumSensorValue0+= sensorValue0[i];
}
meanSensorValue1 = sumSensorValue1/count;
meanSensorValue0 = sumSensorValue0/count;
Irms = (sqrt(meanSensorValue1)*0.06); //60/1000 = 0.06 Calibrating 60 Ampere/1 Volt to give us the value for X amperes
Vrms = (sqrt(meanSensorValue0)*0.3565); // Multiplying with 356.5(the product of ratios of 9V and 12 V transformer) gives the measured voltage in mV.. dividing by 1000 to bring it to Volts from mV
float appPower;
appPower = Vrms*Irms;
float Vsense=0;
float LastVsense=0;
float Isense=0;
float LastIsense=0;
float phase;
float mean_phase=0;
float counter=0;
unsigned long timer;
for(int i=0;i<200;i++)
{
// put your main code here, to run repeatedly:
Isense=analogRead(A1)*4.8-3200;
Vsense=analogRead(A0)*4.8-3220;
if(Vsense>= 0 && LastVsense<0 && Isense<0 )
{
timer = micros();
do{
Isense=analogRead(A1)*4.8-3200;
}while(!(Isense>=0));
timer = micros()-timer;
phase = (timer*360.0)/20000.0;
mean_phase+=phase;
counter+=1.0;
}else;
if(Isense >= 0 && LastIsense < 0 && Vsense < 0 )
{
timer = micros();
do{
Vsense=analogRead(A0)*4.8-3200;
}while(!(Vsense>=0));
timer = micros()-timer;
phase = (timer*360.0)/20000.0;
mean_phase+=phase;
counter+=1.0;
}else;
LastIsense = Isense;
LastVsense = Vsense;
}
mean_phase= mean_phase/counter;
float realPower;
float powerFactor;
float phase_rad= mean_phase*PI/180.0;
powerFactor =cos(phase_rad); //phase converted to radian for cosine function
realPower = Vrms*Irms*powerFactor;
String dataString = "";
float h = dht.readHumidity();
float t = dht.readTemperature();
if (isnan(t) || isnan(h)) {
Serial.println("#Failed to read from DHT");
} else {
dataString+=now.year(), DEC;
dataString+="/";
dataString+=now.month(), DEC;
dataString+="/";
dataString+=now.day(), DEC;
dataString+=" ";
dataString+=now.hour(), DEC;
dataString+=":";
dataString+=now.minute(), DEC;
dataString+=":";
dataString+=now.second(), DEC;
dataString+=" ";
dataString+=Vrms;
dataString+=" ";
dataString+=Irms;
dataString+=" ";
dataString+=mean_phase;
dataString+=" ";
dataString+=powerFactor;
dataString+=" ";
dataString+=appPower;
dataString+=" ";
dataString+=realPower;
dataString+=" ";
dataString+=h;
dataString+=" ";
dataString+=t;
}
// open the file. note that only one file can be open at a time,
// so you have to close this one before opening another.
File dataFile = SD.open("datalog.dat", FILE_WRITE);
// if the file is available, write to it:
if (dataFile) {
dataFile.println(dataString);
dataFile.close();
// print to the serial port too:
Serial.println(dataString);
}
// if the file isn't open, pop up an error:
else {
Serial.println("#error opening datalog.dat");
}
delay(10000);
}
Although the program is using the correct value i.e., 0.9962 in further computations...
That points to the issue being in your printing code.
More specifically, I suspect that this line might be causing trouble:
dataString+=powerFactor;
You are using the String class, so WString.cpp is the relevant file.
If we inspect it, we find that on line 409 (at least, in my version of Arduino, 1.6.7 IIRC), the + operator is declared for floats, and it simply calls concat(float), which can be found on line 323:
unsigned char String::concat(float num)
{
char buf[20];
char* string = dtostrf(num, 4, 2, buf);
return concat(string, strlen(string));
}
If you read the dtostrf docs, you will find that this is converting a double (the float gets promoted) to a string with a width of 4 and 2 digits of precision.
The easiest way to get around this is to use dtostrf to convert the float to a string with the precision you want, and then append that string to your String instance.
I want to do project which will use GPS & GSM module, use Arduino, take data from GPS(GY-GPS/NEO6MV2) and send by GSM(SIM900 GSM/GPRS Module ) to my phone. I am using separate GPS module
I try this code but still have problem.
#include <SoftwareSerial.h>
#include "SIM900.h"
#include <TinyGPS.h>
#include "sms.h"
SMSGSM sms;
TinyGPS gps;
SoftwareSerial ss(4, 3);
SoftwareSerial SIM900(7, 8);
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);
String strL, strN, message, textForSMS;
char charL[10], charN[10], text[200];
int m = 1;
boolean started = false;
void setup()
{
Serial.begin(9600);
ss.begin(9600);
gsm.begin(9600);
}
void loop()
{
float flat, flon;
unsigned long age, date, time, chars = 0;
unsigned short sentences = 0, failed = 0;
gps.f_get_position(&flat, &flon, &age);
textForSMS = "Moosa Home"; //testing gps from here
Serial.println(textForSMS);
Serial.println(flat, 6);
Serial.println(flon, 6);
Serial.print("longitude: ");
print_float(flat, TinyGPS::GPS_INVALID_F_ANGLE, 10, 6);
Serial.println("");
Serial.print("latitude : ");
print_float(flon, TinyGPS::GPS_INVALID_F_ANGLE, 10, 6);
smartdelay(1000);
Serial.println(""); //till here
delay(1000);
if (m == 5) //send sms on third reading
{
Serial.println("XXXXXXXXX"); //to check whether 'if' works
dtostrf(flat, 4, 6, charL);
for (int i = 0; i < 10; i++)
{
strL += charL[i];
}
dtostrf(flon, 4, 6, charN);
for (int i = 0; i < 10; i++)
{
strN += charN[i];
}
message = "Home";
message = message + "/nLat: ";
message = message + strL;
message = message + "/nLon: ";
message = message + strN;
message.toCharArray(text, 250);
Serial.println(text);
if (sms.SendSMS("+999999999999999", text))
{
Serial.println("\nSMS sent OK.");
}
else
{
Serial.println("\nError sending SMS.");
}
do {} while (1);
}
m++;
}
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( 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_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);
}
I receive SMS
Home/nLat:1000.00000/nLon:1000.00000`
where is my mistake in this code?
I am sure Gps & gsm work properly
Using TinyGPS on SoftwareSerial + a loop() structure using delay(1000), has very low odds of working. The m counter is really useless here, because loop() will execute 1000's of times while the GPS characters are arriving. And doing a get_position is useless, because you may not have any GPS data yet.
Basically, loop() should be constantly running, without delays. When something important happens (like getting all of a GPS sentence, or enough time has passed), that's when you do your other work (like send an SMS message). The TinyGPS smartDelay is not smart.
You should restructure the loop to look more like this example from the NeoGPS library. All the non-GPS work should be performed where the digitalWrite is in that example (line 62). That's where you would take the time to send an SMS.
The TinyGPS examples would require a complete rewrite to do what you want. They are fine by themselves, but it is difficult to extend them to do other things, like send an SMS. As I said, the loop structure must change.
I suggest taking a look at the NeoGPS library I wrote, as the examples are more robust. The library also uses much less RAM and CPU time, but that isn't a big problem if all you need to do is send an SMS message. If you do want to try it, be sure to review the default SoftwareSerial choice.
If you get the simple NMEAblink.ino example to work, I would suggest trying NMEA.ino. Then insert your code into the doSomeWork function. Most of what you have in loop needs to go in the doSomeWork function, which is called only when a complete RMC sentence is received.
Regardless of which library you use, you also need to check whether the data is valid. What if your GPS isn't receiving any satellites? It may still send an RMC sentence, but there won't be any lat/lon data. You probably shouldn't send an SMS if the location field is not valid.