Shifting files into a header - "String does ot name a type"

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
"
:smiley:

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

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

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);

image

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:

1 Like