ISO C++ forbids declaration of 'init' with no type

Getting the following errors compiling a sketch for a DOIT ESP32 DEVKIT V1 board, and would like to ask for some help in figuring what is going on. This script will load on a Mega 2560 with these errors, but fails on the DOIT. Unfortunately, I have zero coding experience, and this is a steep learning curve.

The ESP32 is connected to a Megasquirt 3 ECU via canbus. It works as I've used a different script to send analog values to the MS3.

In file included from C:\Users\mr_sm\Documents\Arduino\broadcast_and_GPIOADC_tuotanto\broadcast_and_GPIOADC_tuotanto.ino:8:
c:\Users\mr_sm\Documents\Arduino\libraries\broadcast_and_GPIOADC_tuotanto/MBAmbientTemp.h:15:9: error: ISO C++ forbids declaration of 'init' with no type [-fpermissive]
15 | init(int inputPin, int measureCurrentPin);
| ^~~~
In file included from C:\Users\mr_sm\Documents\Arduino\broadcast_and_GPIOADC_tuotanto\broadcast_and_GPIOADC_tuotanto.ino:15:
c:\Users\mr_sm\Documents\Arduino\libraries\broadcast_and_GPIOADC_tuotanto/MBOilPressure.h:17:9: error: ISO C++ forbids declaration of 'init' with no type [-fpermissive]
17 | init(int inputPin, int measureCurrentPin);
| ^~~~
In file included from C:\Users\mr_sm\Documents\Arduino\broadcast_and_GPIOADC_tuotanto\broadcast_and_GPIOADC_tuotanto.ino:22:
c:\Users\mr_sm\Documents\Arduino\libraries\broadcast_and_GPIOADC_tuotanto/MBFuelAmount.h:16:9: error: ISO C++ forbids declaration of 'init' with no type [-fpermissive]
16 | init(int inputPin, int measureCurrentPin);
| ^~~~

exit status 1

Compilation error: exit status 1


#include <SPI.h>
#include <mcp2515.h> //https://github.com/autowp/arduino-mcp2515
#include <MegaCAN.h> //https://github.com/mantonakakis1/MegaCAN

//Sensor libraries

  //Ambient temperature
    #include <MBAmbientTemp.h> 
    AmbientTemp AT;
    
    #define AT_EXE_INTERVAL 200 // How often Ambient Temperature is measured (ms)
    unsigned long ATlastExecutedMillis = 0; // Variable to save the last executed time
  
  //Oil Pressure
    #include <MBOilPressure.h>
    OilPressure OP;
  
    #define OP_EXE_INTERVAL 50 // How often Oil Pressure is measured (ms)
    unsigned long OPlastExecutedMillis = 0; // Variable to save the last executed time
  
  //Fuel Amount
    #include <MBFuelAmount.h>
    FuelAmount FA;
    #define FA_EXE_INTERVAL 100 // How often Fuel Amount is measured (ms)
    #define FW_EXE_INTERVAL 100 // How often Fuel Warning is measured (ms)
    unsigned long FAlastExecutedMillis = 0; // Variable to save the last executed time
    unsigned long FWlastExecutedMillis = 0; // Variable to save the last executed time

//MegaCAN
//#define CELSIUS // MegaCAN uses Fahrenheit, which is no good. This transforms broadcasted temperatures to Celsius

//MegaCAN
const uint32_t baseID = 1512; // Must set to match Megasquirt Settings!
const uint32_t finalID = baseID + 3; // Must set to match Megasquirt Settings configured in TunerStudio! The last group of data broadcasted.

//MCP2515 related
struct can_frame receivedFrame; 
MCP2515 mcp2515(5);  //CS at D10

MegaCAN MegaCAN; // For processed Megasquirt CAN protocol messages 

MegaCAN_message_t recMsgMSC; // Stores received message from Megasquirt, Megasquirt CAN protocol
MegaCAN_message_t respMsgMSC; // Stores response message back to Megasquirt, Megasquirt CAN protocol
MegaCAN_broadcast_message_t bCastMsg; // Stores unpacked Megasquirt broadcast data, e.g. bCastMsg.rpm

struct can_frame respMsg; // Actual response message back to Megasquirt, MSCAN protocol

uint16_t GPIOADC[8] = { 0 }; // Stores values to send to Megasquirt, 4 ADCS for each message

uint16_t adc0 = 0; 
uint16_t adc1 = 0;
uint16_t adc2 = 0;
uint16_t adc3 = 0;
uint16_t adc4 = 0;
uint16_t adc5 = 0;
uint16_t adc6 = 0;
uint16_t adc7 = 0; 

//Variables for averaging of sensor values
  //AT
  const int ATnumReadings = 10;
  
  int ATreadings[ATnumReadings];    // The readings from the analog input
  int ATreadIndex = 0;              // The index of the current reading
  int ATtotal = 0;                  // The running total
  int ATaverage = 0;                // The average

  //OP
  const int OPnumReadings = 10;
  
  int OPreadings[OPnumReadings];    // The readings from the analog input
  int OPreadIndex = 0;              // The index of the current reading
  int OPtotal = 0;                  // The running total
  int OPaverage = 0;                // The average

  //FA
  const int FAnumReadings = 100;
  
  int FAreadings[FAnumReadings];    // The readings from the analog input
  int FAreadIndex = 0;              // The index of the current reading
  int FAtotal = 0;                  // The running total
  int FAaverage = 0;                // The average

  //FW
  const int FWnumReadings = 100;
  
  int FWreadings[FWnumReadings];    // The readings from the input
  int FWreadIndex = 0;              // The index of the current reading
  int FWtotal = 0;                  // The running total
  int FWaverage = 0;                // The average


void initializeCAN() {
  mcp2515.reset();
  mcp2515.setBitrate(CAN_500KBPS, MCP_8MHZ); //Megasquirt specific 500kbs
  mcp2515.setNormalMode();
  
}

void canMShandler(const can_frame &msg) {
  // For Megasquirt CAN protocol, MS is requesting data:
  if ((msg.can_id & CAN_EFF_FLAG) != 0) { //Data request from MS uses extended flag, there may be a better way to implement this with more advanced applications, works fine for sending data to MS GPIOADC
    sendDataToMS(msg); //Due to the extended flag, we assume this is a MS data request and run the function to send data to MS, passing the message received from MS to the sendDataToMS function
  }
  // For Megasquirt CAN broadcast data:
  else { //Broadcast data from MS does not use extended flag, therefore a standard message from MS will contain broadcast data
    //Unpack megasquirt broadcast data into bCastMsg:
    MegaCAN.getBCastData(msg.can_id, msg.data, bCastMsg); //baseID fixed in library based on const parameter entered for baseID above - converts the raw CAN id and buf to bCastMsg format
    if (msg.can_id == finalID) {
      /*~~~Final message for this batch of data, do stuff with the data - this is a simple example~~~*/
      /*
      Serial.print(bCastMsg.map); Serial.print(" | "); //should be kPa
      Serial.print(bCastMsg.rpm); Serial.print(" | "); //should be rpm
      Serial.println(bCastMsg.tps);                      //should be %
      */
    }
  }
}

void sendDataToMS(can_frame msg) {
  MegaCAN.processMSreq(msg.can_id, msg.data, recMsgMSC); // Unpack request message ("msg") from MS into recMsgMS

  if (recMsgMSC.core.toOffset == 2) { //For GPIOADC0-3
    GPIOADC[0] = adc0; //Ambient Temperature
    GPIOADC[1] = adc1; //Oil Pressure
    GPIOADC[2] = adc2; //Fuel Amount
    GPIOADC[3] = adc3; //Fuel Warning. ADC is not the best solution for an on/off, but will do
    MegaCAN.setMSresp(recMsgMSC, respMsgMSC, GPIOADC[0], GPIOADC[1], GPIOADC[2], GPIOADC[3]); //Packs the GPIOADC0-3 values into "respMsgMSC"
  }
  else if (recMsgMSC.core.toOffset == 10) { //For GPIOADC4-7
    GPIOADC[4] = adc4; //vacant
    GPIOADC[5] = adc5; //vacant
    GPIOADC[6] = adc6; //vacant
    GPIOADC[7] = adc7; //vacant
    MegaCAN.setMSresp(recMsgMSC, respMsgMSC, GPIOADC[4], GPIOADC[5], GPIOADC[6], GPIOADC[7]); //Packs the GPIOADC4-7 values into "respMsgMSC"
  }
  
  // Send response to Megasquirt using MSCAN protocol:
  respMsg.can_id = respMsgMSC.responseCore | CAN_EFF_FLAG; //CAN_EFF_FLAG added to the end of response message, otherwise MS will not use it
  respMsg.can_dlc = sizeof(respMsgMSC.data.response);
  for (int i = 0; i < respMsg.can_dlc; i++) {
    respMsg.data[i] = respMsgMSC.data.response[i];
  }
  
  mcp2515.sendMessage(&respMsg); //Sends the GPIOADC values stored in respMsg over CAN to Mesasquirt
  //Serial.println("Data sent to Megasquirt");
}

void setup() 
  {
  while (!Serial);
  Serial.begin(9600);
  Serial.println("MAP | RPM | TPS");
  initializeCAN();
  pinMode(33, INPUT); //Fuel warning indicator switch
//Setup Ambient Temp readings
  for (int ATthisReading = 0; ATthisReading < ATnumReadings; ATthisReading++) //As long as thisReading is smaller than numReadings, add to thisReading
    {
    ATreadings[ATthisReading] = 0;
    }
  AT.init(2,34); //Current from D34 and measuring voltage from A2  

//Setup Oil Pressure readings
  for (int OPthisReading = 0; OPthisReading < OPnumReadings; OPthisReading++) //As long as thisReading is smaller than numReadings, add to thisReading
    {
    OPreadings[OPthisReading] = 0;
    }
  OP.init(13,35); //Current from D35 and measuring voltage from A0  

//Setup Fuel Amount readings
  for (int FAthisReading = 0; FAthisReading < FAnumReadings; FAthisReading++) //As long as thisReading is smaller than numReadings, add to thisReading
    {
    FAreadings[FAthisReading] = 0;
    }
  FA.init(4,32); //Current from D32 and measuring voltage from A1  
  }

void loop() {
  
onReceived(); //Read messages from CAN-bus
getAT(); //Read Ambient Temperature and handle signal
getOP(); //Read Oil Pressure and handle signal
getFA(); //Read Fuel Amount and handle signal
getFW(); //Read Fuel Warning switch and handle signal
}

void onReceived() 
//Listen to CAN-bus and run canMShandler after
{
    
  if (mcp2515.readMessage(&receivedFrame) == MCP2515::ERROR_OK) 
    {
      canMShandler(receivedFrame);
      /*
      Serial.println("Received message:");
      Serial.println("  ID: 0x" + String(receivedFrame.can_id, HEX));
      Serial.println("  DLC: " + String(receivedFrame.can_dlc));
      Serial.println("  Data: " + String(receivedFrame.data[0]) + " " +
                                  String(receivedFrame.data[1]) + " " +
                                  String(receivedFrame.data[2]) + " " +
                                  String(receivedFrame.data[3]) + " " +
                                  String(receivedFrame.data[4]) + " " +
                                  String(receivedFrame.data[5]) + " " +
                                  String(receivedFrame.data[6]) + " " +
                                  String(receivedFrame.data[7]));
    */
  }
}

void getAT()
{
  unsigned long ATcurrentMillis = millis(); // Record current time

  if (ATcurrentMillis - ATlastExecutedMillis >= AT_EXE_INTERVAL) //If elapsed time from last execution is more than the specified interval 
    {
      ATlastExecutedMillis = ATcurrentMillis; // save the last executed time
      //AT
      AT.measure(5,1024,10000,3007,3848,false); //float VCC,int _ADC, float R1, int R25, int Beta, bool prints
      ATtotal = ATtotal - ATreadings[ATreadIndex]; // subtract the last reading
      ATreadings[ATreadIndex] = AT.ambienttempvalue*10; // read from the sensor
      ATtotal = ATtotal + ATreadings[ATreadIndex]; // add the reading to the total
      ATreadIndex = ATreadIndex + 1; // advance to the next position in the array
      if (ATreadIndex >= ATnumReadings) // if we're at the end of the array...
        {
          ATreadIndex = 0; // ...wrap around to the beginning
        }
      ATaverage = ATtotal / ATnumReadings; // calculate the average
      adc0 = ATaverage; // Insert average to variable adc0
      //Serial.println(adc0);
    }  
}

void getOP()
{
  unsigned long OPcurrentMillis = millis(); // Record current time

  if (OPcurrentMillis - OPlastExecutedMillis >= OP_EXE_INTERVAL) //If elapsed time from last execution is more than the specified interval
    {
      OPlastExecutedMillis = OPcurrentMillis; // save the last executed time
      //OP
      OP.measure(5,1024,100,10,69,129,184,false); //float VCC, int _ADC, float R1, int R_0BAR, int R_1BAR, int R_2BAR, int R_3BAR, bool prints
      OPtotal = OPtotal - OPreadings[OPreadIndex]; // subtract the last reading
      OPreadings[OPreadIndex] = OP.oilpressurevalue*100; // read from the sensor
      OPtotal = OPtotal + OPreadings[OPreadIndex]; // add the reading to the total
      OPreadIndex = OPreadIndex + 1; // advance to the next position in the array
      if (OPreadIndex >= OPnumReadings) // if we're at the end of the array...
        {
          OPreadIndex = 0; // ...wrap around to the beginning:
        }
      OPaverage = OPtotal / OPnumReadings; // calculate the average
      adc1 = OPaverage; // Insert average to variable adc1
      //Serial.println(adc1);
    }  
}

void getFA()
{
  unsigned long FAcurrentMillis = millis(); // Record current time

  if (FAcurrentMillis - FAlastExecutedMillis >= FA_EXE_INTERVAL) //If elapsed time from last execution is more than the specified interval
    {
      FAlastExecutedMillis = FAcurrentMillis; // save the last executed time
      //FA
      FA.measure(5,1024,10,2,78,false); //float VCC,int _ADC, float R1, int R_Full, int R_Empty, bool prints
      FAtotal = FAtotal - FAreadings[FAreadIndex]; // subtract the last reading
      FAreadings[FAreadIndex] = FA.fuelamountvalue*100; // read from the sensor
      FAtotal = FAtotal + FAreadings[FAreadIndex]; // add the reading to the total
      FAreadIndex = FAreadIndex + 1; // advance to the next position in the array
      if (FAreadIndex >= FAnumReadings) // if we're at the end of the array...
        {
          FAreadIndex = 0; // ...wrap around to the beginning
        }
      FAaverage = FAtotal / FAnumReadings; // calculate the average
      adc2 = FAaverage; // Insert average to variable adc2
      //Serial.println(adc2);
    }  
}
void getFW()
{
 unsigned long FWcurrentMillis = millis(); // Record current time

  if (FWcurrentMillis - FWlastExecutedMillis >= FW_EXE_INTERVAL) //If elapsed time from last execution is more than the specified interval
    {
      FWlastExecutedMillis = FWcurrentMillis; // save the last executed time
      //FW
      FWtotal = FWtotal - FWreadings[FWreadIndex]; // subtract the last reading
      int sensorVal = digitalRead(33); // read port status:
      if (sensorVal = LOW) // If the switch is closed...
      {
        FWreadings[FWreadIndex] = 1; //...reading is one
      }
      else
      {
        FWreadings[FWreadIndex] = 0; //...reading is zero
      }
      FWtotal = FWtotal + FWreadings[FWreadIndex]; // add the reading to the total
      FWreadIndex = FWreadIndex + 100; // advance to the next position in the array
      // if we're at the end of the array...
      if (FWreadIndex >= FWnumReadings) 
        {
          FWreadIndex = 0; // ...wrap around to the beginning
        }
    FWaverage = FWtotal / FWnumReadings; // calculate the average
    adc3 = FWaverage; // Insert average to variable adc3
    //Serial.println(adc3);
    }  
}

IIRC, the ESP32 core now treats warning as errors. That's why it's failing on the DOIT but gets by on the 2560.

If the routine in question doesn't return a value, declare it as void. If it does return a value, it likely defaults to an int, so declare the routine as an int. Wow, I can't remember the last time I saw code that relied on the return type of a function defaulting to an int!

Thanks for the reply. That's what I guessed. This is a script from a few years ago written to deal with an ECU that's been around for longer than the 2560.

This is one of the four input codes in the library. Can you show me how to modify it according to your explanation please?

I believe it expects to return a value since this is measuring ambient temperature.

/*!
 * This is a library for NTC-based temperature sensors. 
 * 
 * Written by Kaius Yli-Pietilä.
 * BSD license, all text above must be included in any redistribution
 */

#ifndef MBAmbientTemp_h
#define MBAmbientTemp_h
#include "Arduino.h" 

class AmbientTemp 
{
      public:
        init(int inputPin, int measureCurrentPin);
        float ambienttempvalue = 0.0;
        float inputvoltage = 0.0;
        int _ADC = 0;
        float Percentagestep = 0.0;
        void measure(float VCC,int _ADC, float R1, int R25, int Beta, bool prints);
      private:
      int _inputPin;
      int _measureCurrentPin;
};
#endif


That's just the header. I'd have to see the actual init function itself to be sure.

But based on the way it's used in the sketch you showed, no return value is ever used, so I'd plumb for void. You'd have to change the function return type in the .cpp file as well.

It would be helpful if you told us where you got the library. Please post a GitHub link.

I'm assuming this is what you're wanting to see.

Thanks again for reviewing...

#include "MBAmbientTemp.h"
#include <Arduino.h>
#include <math.h>

AmbientTemp::init(int inputPin, int measureCurrentPin)
{
pinMode(inputPin, INPUT);
pinMode(measureCurrentPin, OUTPUT);
_inputPin = inputPin;
_measureCurrentPin = measureCurrentPin;
}


void AmbientTemp::measure(float VCC,int _ADC, float R1, int R25, int Beta, bool prints)
{     
      digitalWrite(_measureCurrentPin, HIGH);
      inputvoltage = analogRead(_inputPin)* (VCC/_ADC); // Read voltage and pass to variable


      ambienttempvalue = Beta/((log(((R1*(1/((VCC/inputvoltage)-1)))/R25))+Beta/(25+273.15)))-273.15;

        if(prints==true)
        {
          Serial.print("R25: ");
          Serial.println(R25);
          Serial.print("Beta: ");
          Serial.println(Beta);

          Serial.print("Input voltage at ");
          Serial.print(_inputPin);
          Serial.print(": ");
          Serial.println(inputvoltage);
     
          Serial.print("Ambient temperature: ");
          Serial.println(ambienttempvalue);          
          Serial.print(" °C");
          
          Serial.print("R1 value: ");
          Serial.println(R1);
        }
      digitalWrite(_measureCurrentPin, LOW);       
}
type or paste code here

That's it. Yep, init returns nothing so make its type void and that should fix that.

Thanks again!

I am not able to find where this is on Github. I found this last year on the Microsquirt forum here: MegaCAN: Arduino Library for Megasquirt CAN protocol - Page 3 - Megasquirt Support Forum (MSEXTRA)

The gent whose project is discussed said he made an example in the autowp/srduino GitHub - autowp/arduino-mcp2515: Arduino MCP2515 CAN interface library library, but I don't see the script.

It looks like someone changed the name of the constructor into init() possibly after being told to not use pinMode in the constructor….

1 Like

That's very plausible. I did wonder at the lack of an explicit constructor.

It'd be easy enough to separate out and "Arduino-ize" it as it were:

.h

 public:
   AmbientTemp(int inputPin, int measureCurrentPin);

.cpp

AmbientTemp::AmbientTemp(int inputPin, int measureCurrentPin)
{
   _inputPin = inputPin;
   _measureCurrentPin = measureCurrentPin;
}

void AmbientTemp::begin(void)
{
   pinMode(_inputPin, INPUT);
   pinMode(_measureCurrentPin, OUTPUT);
}

but I'm not sure it'd buy the OP much at this point.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.