I have this wonderful code. This uses the TinyGSM lib to send SMS.
This works perfectly fine
#include "sim.h"
const char simPIN[] = "3000";
#define SMS_TARGET "+49000"
#define TINY_GSM_MODEM_SIM800
#define TINY_GSM_RX_BUFFER 1024
#include <TinyGsmClient.h>
#define MODEM_RST 5
#define MODEM_PWKEY 4
#define MODEM_POWER_ON 23
#define MODEM_TX 27
#define MODEM_RX 26
#define I2C_SDA 21
#define I2C_SCL 22
#define SerialMon Serial
#define SerialAT Serial1
// Einkommentieren für eine Debugausgabe
//#define DUMP_AT_COMMANDS
#ifdef DUMP_AT_COMMANDS
#include <StreamDebugger.h>
StreamDebugger debugger(SerialAT, SerialMon);
TinyGsm modem(debugger);
#else
TinyGsm modem(SerialAT);
#endif
#define IP5306_ADDR 0x75
#define IP5306_REG_SYS_CTL0 0x00
void setup() {
SerialMon.begin(115200);
pinMode(MODEM_PWKEY, OUTPUT);
pinMode(MODEM_RST, OUTPUT);
pinMode(MODEM_POWER_ON, OUTPUT);
digitalWrite(MODEM_PWKEY, LOW);
digitalWrite(MODEM_RST, HIGH);
digitalWrite(MODEM_POWER_ON, HIGH);
// Set GSM module baud rate and UART pins
SerialAT.begin(57600, SERIAL_8N1, MODEM_RX, MODEM_TX);
delay(3000);
SerialMon.println("Initializing modem...");
if (!modem.restart())
{
SerialMon.println("Restart failed");
}
modem.simUnlock(simPIN);
delay(1000);
if (!modem.waitForNetwork())
{
SerialMon.println("No Network connection");
}
if(sendAT("AT+CMGF=1").indexOf("OK") < 0)
{
SerialMon.println("SMS Txt mode Error");
}
if (modem.sendSMS(SMS_TARGET, "Test SMS")) {
SerialMon.println("SMS success");
}
else {
SerialMon.println("SMS failed to send");
}
}
void loop() {
String SMSText= "test";
if (modem.sendSMS(SMS_TARGET, SMSText)) {
SerialMon.println("SMS success");
SerialMon.println(SMSText);
}
else {
SerialMon.println("SMS failed to send");
}
}
String sendAT(String command)
{
String response = "";
SerialAT.println(command);
while(!SerialAT.available());
response = SerialAT.readString();
return response;
}
Now I want to shift all the functionalities into a header (for reuse purposes), so at the end, i want to have only one function "SendSMS()"
When I try to shift the last function in the Header, i get the error "'String'" does not name a type"
My header files look like followed:
sim.cpp
#include "sim.h"
//send command to modem
String sendAT(String command)
{
String response = "";
SerialAT.println(command);
while(!SerialAT.available());
response = SerialAT.readString();
return response;
}
sim.h
String sendAT(String command);
I deleted this function also in the main and included sim.h
Try #including Arduino.h in the .h file
Thank you! Seems this error is now away.
I have now a new error
"'SerialAT' was not declared in this scope
"
Please post the full error message
1 Like
okay, I moved forward. Solution was to include another lib also in the .h
Now I have the error
"XXX\sim.h:33: multiple definition of `modem';
sketch\sim.cpp.o:
XXX\sim.h:33: first defined here
collect2.exe: error: ld returned 1 exit status"
my main:
#include "sim.h"
void setup() {
SerialMon.begin(115200);
pinMode(MODEM_PWKEY, OUTPUT);
pinMode(MODEM_RST, OUTPUT);
pinMode(MODEM_POWER_ON, OUTPUT);
digitalWrite(MODEM_PWKEY, LOW);
digitalWrite(MODEM_RST, HIGH);
digitalWrite(MODEM_POWER_ON, HIGH);
// Set GSM module baud rate and UART pins
SerialAT.begin(57600, SERIAL_8N1, MODEM_RX, MODEM_TX);
delay(3000);
SerialMon.println("Initializing modem...");
if (!modem.restart())
{
SerialMon.println("Restart failed");
}
modem.simUnlock(simPIN);
delay(1000);
if (!modem.waitForNetwork())
{
SerialMon.println("No Network connection");
}
if(sendAT("AT+CMGF=1").indexOf("OK") < 0)
{
SerialMon.println("SMS Txt mode Error");
}
if (modem.sendSMS(SMS_TARGET, "Test SMS")) {
SerialMon.println("SMS success");
}
else {
SerialMon.println("SMS failed to send");
}
}
int x=0;
void loop() {
x=x+1;
String SMSText= " count: " + String(x);
sendSMS(String SMSText
}
My sim.cpp:
#include "sim.h"
//send command to modem
String sendAT(String command)
{
String response = "";
SerialAT.println(command);
while(!SerialAT.available());
response = SerialAT.readString();
return response;
}
void sendSMS(String SMSText){
if (modem.sendSMS(SMS_TARGET, SMSText)) {
SerialMon.println("SMS success");
SerialMon.println(SMSText);
}
else {
SerialMon.println("SMS failed to send");
}
}
my sim.h
#pragma once
#include "Arduino.h"
const char simPIN[] = "3000";
#define SMS_TARGET "+49000"
#define TINY_GSM_MODEM_SIM800
#define TINY_GSM_RX_BUFFER 1024
#include <TinyGsmClient.h>
#define MODEM_RST 5
#define MODEM_PWKEY 4
#define MODEM_POWER_ON 23
#define MODEM_TX 27
#define MODEM_RX 26
#define I2C_SDA 21
#define I2C_SCL 22
#define SerialMon Serial
#define SerialAT Serial1
// Einkommentieren für eine Debugausgabe
//#define DUMP_AT_COMMANDS
#ifdef DUMP_AT_COMMANDS
#include <StreamDebugger.h>
StreamDebugger debugger(SerialAT, SerialMon);
TinyGsm modem(debugger);
#else
TinyGsm modem(SerialAT);
#endif
#define IP5306_ADDR 0x75
#define IP5306_REG_SYS_CTL0 0x00
String sendAT(String command);
void sendSMS(String SMSText);
My idea is that the header is compiled multiple times. pragma once is not avoiding this. But maybe i am wrong. Dont know
Try using an explicit guard against the .h being compiled twice
#ifndef SIM_h
#define SIM_h
//code goes here
#endif
DerPeter:
#include "sim.h"
//send command to modem
String sendAT(String command)
{
String response = "";
SerialAT.println(command);
while(!SerialAT.available());
response = SerialAT.readString();
return response;
}
void sendSMS(String SMSText){
if (modem.sendSMS(SMS_TARGET, SMSText)) {
SerialMon.println("SMS success");
SerialMon.println(SMSText);
}
else {
SerialMon.println("SMS failed to send");
}
}
Shouldnt pragm once do this job?
But with #ifned ... it is not working, too
The problem is exactly what the linked stated. You've defined the object 'modem' in sim.h. But, sim.h gets #included in both the main .ino file and sim.cpp. So now it's defined in two places. Those two files get compiled without issue. But, when the linker tries to resolve the references and put everything together it finds two definitions of the same object.
Variables (objects) should only be declared in the .h file. See: https://www.geeksforgeeks.org/difference-between-definition-and-declaration/
You can also see My Post #5 Here for a basic guide to breaking projects into separate .cpp / .h files.
1 Like
gfvalvo:
The problem is exactly what the linked stated. You've defined the object 'modem' in sim.h. But, sim.h gets #included in both the main .ino file and sim.cpp. So now it's defined in two places. Those two files get compiled without issue. But, when the linker tries to resolve the references an
Thanks a lot for the help!
I am a little bit confused how to go on with shifting the definition because there is a #ifndef - clause before its definition. The other thing is that TinyGsm modem; in the .h leads to the error that one argument is missing.
I am confused how to simple declare it
Try this:
Move to the the .cpp file:
#ifdef DUMP_AT_COMMANDS
#include <StreamDebugger.h>
StreamDebugger debugger(SerialAT, SerialMon);
TinyGsm modem(debugger);
#else
TinyGsm modem(SerialAT);
#endif
In the .h file:
extern TinyGsm modem;
In file included from XXXX\sim.cpp:1:
sim.h:8:8: error: 'TinyGsm' does not name a type
extern TinyGsm modem;
^~~~~~~
In file included from XXX\sketch_jun29d.ino:2:
sim.h:8:8: error: 'TinyGsm' does not name a type
extern TinyGsm modem;
^~~~~~~
XXXX\sketch_jun29d.ino: In function 'void setup()':
sketch_jun29d:19:8: error: 'modem' was not declared in this scope
if (!modem.restart())
^~~~~
XXXX\sketch_jun29d.ino:19:8: note: suggested alternative: 'mode_t'
if (!modem.restart())
^~~~~
mode_t
sketch_jun29d:24:3: error: 'modem' was not declared in this scope
modem.simUnlock(simPIN);
^~~~~
XXXX\sketch_jun29d.ino:24:3: note: suggested alternative: 'mode_t'
modem.simUnlock(simPIN);
^~~~~
mode_t
exit status 1
'TinyGsm' does not name a type
I can't see your updated code from here. Post all 3 files again.
main:
#include "sim.h"
void setup() {
SerialMon.begin(115200);
pinMode(MODEM_PWKEY, OUTPUT);
pinMode(MODEM_RST, OUTPUT);
pinMode(MODEM_POWER_ON, OUTPUT);
digitalWrite(MODEM_PWKEY, LOW);
digitalWrite(MODEM_RST, HIGH);
digitalWrite(MODEM_POWER_ON, HIGH);
// Set GSM module baud rate and UART pins
SerialAT.begin(57600, SERIAL_8N1, MODEM_RX, MODEM_TX);
delay(3000);
SerialMon.println("Initializing modem...");
if (!modem.restart())
{
SerialMon.println("Restart failed");
}
modem.simUnlock(simPIN);
delay(1000);
if (!modem.waitForNetwork())
{
SerialMon.println("No Network connection");
}
if(sendAT("AT+CMGF=1").indexOf("OK") < 0)
{
SerialMon.println("SMS Txt mode Error");
}
if (modem.sendSMS(SMS_TARGET, "Test SMS")) {
SerialMon.println("SMS success");
}
else {
SerialMon.println("SMS failed to send");
}
}
int x=0;
void loop() {
x=x+1;
String SMSText= "Work count: " + String(x);
//sendSMS(String SMSText);
}
sim.cpp
#include "sim.h"
TinyGsm modem(SerialAT);
//send command to modem
String sendAT(String command)
{
String response = "";
SerialAT.println(command);
while(!SerialAT.available());
response = SerialAT.readString();
return response;
}
void sendSMS(String SMSText){
if (modem.sendSMS(SMS_TARGET, SMSText)) {
SerialMon.println("SMS success");
SerialMon.println(SMSText);
}
else {
SerialMon.println("SMS failed to send");
}
}
sim.h
#include "Arduino.h"
//2VTT-LPTS-NG2Z-2HR2Z
extern TinyGsm modem(SerialAT);
const char simPIN[] = "3000";
#define SMS_TARGET "+49000"
#define TINY_GSM_MODEM_SIM800
#define TINY_GSM_RX_BUFFER 1024
#include <TinyGsmClient.h>
#define MODEM_RST 5
#define MODEM_PWKEY 4
#define MODEM_POWER_ON 23
#define MODEM_TX 27
#define MODEM_RX 26
#define I2C_SDA 21
#define I2C_SCL 22
#define SerialMon Serial
#define SerialAT Serial1
// Einkommentieren für eine Debugausgabe
//#define DUMP_AT_COMMANDS
#define IP5306_ADDR 0x75
#define IP5306_REG_SYS_CTL0 0x00
String sendAT(String command);
void sendSMS(String SMSText);
#endif
You can't expect the compiler to know what a 'TinyGsm' is until AFTER you've included the library, can you??? Move the declaration below that:
I predict this will likely be your next "Multiple Definitions" error. Same reason.
Omg you are so right. Didnt sawthat, sorry
To the char array: Saw it already, but wanted to fix the other problem first
So now my .cpp
#include "sim.h"
const char simPIN[] = "3000";
#ifdef DUMP_AT_COMMANDS
#include <StreamDebugger.h>
StreamDebugger debugger(SerialAT, SerialMon);
TinyGsm modem(debugger);
#else
TinyGsm modem(SerialAT);
#endif
//send command to modem
String sendAT(String command)
{
String response = "";
SerialAT.println(command);
while(!SerialAT.available());
response = SerialAT.readString();
return response;
}
void sendSMS(String SMSText){
if (modem.sendSMS(SMS_TARGET, SMSText)) {
SerialMon.println("SMS success");
SerialMon.println(SMSText);
}
else {
SerialMon.println("SMS failed to send");
}
}
my .h
#ifndef SIM_h
#define SIM_h
#include "Arduino.h"
#include <TinyGsmClient.h>
extern TinyGsm modem(SerialAT);
const char simPIN[];
#define SMS_TARGET "+49000"
#define TINY_GSM_MODEM_SIM800
#define TINY_GSM_RX_BUFFER 1024
#define MODEM_RST 5
#define MODEM_PWKEY 4
#define MODEM_POWER_ON 23
#define MODEM_TX 27
#define MODEM_RX 26
#define I2C_SDA 21
#define I2C_SCL 22
#define SerialMon Serial
#define SerialAT Serial1
// Einkommentieren für eine Debugausgabe
//#define DUMP_AT_COMMANDS
#define IP5306_ADDR 0x75
#define IP5306_REG_SYS_CTL0 0x00
String sendAT(String command);
void sendSMS(String SMSText);
#endif
Now i get the error:
"TinyGsmClient.h:118:2: #error "Please define GSM modem model"
^~~~~
exit status 1
"
Go back and look at the move I told you to do. Compare that to the move you did.
If you are mean, that I shifted the lib and not the extern object:
#ifndef SIM_h
#define SIM_h
#include "Arduino.h"
const char simPIN[] = "3000";
#define SMS_TARGET "+49000"
#define TINY_GSM_MODEM_SIM800
#define TINY_GSM_RX_BUFFER 1024
#include <TinyGsmClient.h>
#define MODEM_RST 5
#define MODEM_PWKEY 4
#define MODEM_POWER_ON 23
#define MODEM_TX 27
#define MODEM_RX 26
#define I2C_SDA 21
#define I2C_SCL 22
#define SerialMon Serial
#define SerialAT Serial1
extern TinyGsm modem(SerialAT);
// Einkommentieren für eine Debugausgabe
//#define DUMP_AT_COMMANDS
#define IP5306_ADDR 0x75
#define IP5306_REG_SYS_CTL0 0x00
String sendAT(String command);
void sendSMS(String SMSText);
#endif
like this you mean? still gives a error
(serial AT not defined)
if i move it more forward
#ifndef SIM_h
#define SIM_h
#include "Arduino.h"
const char simPIN[] = "3000";
#define SMS_TARGET "+49000"
#define TINY_GSM_MODEM_SIM800
#define TINY_GSM_RX_BUFFER 1024
#include <TinyGsmClient.h>
#define MODEM_RST 5
#define MODEM_PWKEY 4
#define MODEM_POWER_ON 23
#define MODEM_TX 27
#define MODEM_RX 26
#define I2C_SDA 21
#define I2C_SCL 22
#define SerialMon Serial
#define SerialAT Serial1
extern TinyGsm modem(SerialAT);
// Einkommentieren für eine Debugausgabe
//#define DUMP_AT_COMMANDS
#define IP5306_ADDR 0x75
#define IP5306_REG_SYS_CTL0 0x00
String sendAT(String command);
void sendSMS(String SMSText);
#endif
error: redefinition of 'TinyGsm modem'
TinyGsm modem(SerialAT);
Grasshopper, it may be time to cut you loose so you can learn to solve these problems on your own.
One last hint ... compare how I told you to do the 'extern' declaration to what you did:
gfvalvo:
In the .h file:
extern TinyGsm modem;
1 Like