compile error since IDE 1.5.8

Hi all,

Hi wrote a sketch several months ago on my laptop in the Arduino IDE 1.0.2, which compiled fine (and still does on my laptop). I tried to compile it today on another PC for which I downloaded the latest stable version of the IDE, 1.5.8.

I'm getting a a lot of error messages, of which the first one is 'prog_char' does not name a type. It seems to have something to do with #include .

The sketch is basically a lot of copy and paste from sketches found online.

Any ideas? Thanks!



DATE: 17-06-2014
COMPILE: Arduino IDE 1.0.2
BOARD: Arduino Ethernet
DESCRIPTION: Hosts a webpage on specified IP-address with buttons LEFT and RIGHT to turn AR-500 from Hygain.

prog_char string_a[] PROGMEM = "";
prog_char string_b[] PROGMEM = "";
prog_char string_c[] PROGMEM = "";
prog_char string_d[] PROGMEM = "";
prog_char string_e[] PROGMEM = "";
prog_char string_f[] PROGMEM = "";
prog_char string_g[] PROGMEM = "";
prog_char string_h[] PROGMEM = "";
prog_char string_i[] PROGMEM = "";
prog_char string_j[] PROGMEM = "";
prog_char string_u[] PROGMEM = "";
prog_char string_l[] PROGMEM = "";
prog_char string_initial[] PROGMEM = "";
prog_char string_memory[] PROGMEM = "";
prog_char string_left[] PROGMEM = "";
prog_char string_right[] PROGMEM = "";

PROGMEM const char *string_table[] =       // change "string_table" name to suit
  char buffer[120];

IRsend irsend;
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //physical mac address
byte ip[] = { 192, 168, 255, 10 }; // ip in lan
byte gateway[] = { 192, 168, 255, 1 }; // internet access via router
byte subnet[] = { 255, 255, 255, 0 }; //subnet mask
EthernetServer server(80); //server port

String readString; 

void setup(){

  //start Ethernet
  Ethernet.begin(mac, ip, gateway, gateway, subnet);
  //enable serial data print 
  Serial.println("server multi pin button test 1.0"); // so I can keep track of what is loaded

void loop(){
  // Create a client connection
  EthernetClient client = server.available();
  if (client) {
    while (client.connected()) {
      if (client.available()) {
        char c =;

        //read char by char HTTP request
        if (readString.length() < 100) {

          //store characters to string 
          readString += c; 

        //if HTTP request has ended
        if (c == '\n') {

          Serial.println(readString); //print to serial monitor for debuging 

          client.println("HTTP/1.1 200 OK"); //send new page
          client.println("Content-Type: text/html");

          client.println("EuroLinx AR-500 Antenna Rotator");


AR-500 Antenna Rotator

");                             for(int i=14;i<16;i++){           strcpy_P(buffer, (char*)pgm_read_word(&(string_table[i]))); client.print(buffer);}                     client.print(" ");         for(int i=0;i<4;i++){           strcpy_P(buffer, (char*)pgm_read_word(&(string_table[i]))); client.print(buffer);}           client.print(" ");           for(int i=4;i<8;i++){           strcpy_P(buffer, (char*)pgm_read_word(&(string_table[i]))); client.print(buffer);}           client.print(" ");           for(int i=8;i<12;i++){           strcpy_P(buffer, (char*)pgm_read_word(&(string_table[i]))); client.print(buffer);}           client.print(" ");           for(int i=12;i<14;i++){           strcpy_P(buffer, (char*)pgm_read_word(&(string_table[i]))); client.print(buffer);}                 client.print("

");         client.print("(c) EuroLinx 2014, written by Jens Vanhoof.");                               client.println("");           client.println("");           delay(1);                     client.stop();                               if(readString.indexOf('8') >0){                   for (int i = 0; i < 3; i++) {irsend.sendNEC(0x609F8877,32);  delay(40);} //links draaien             }                       if(readString.indexOf('9') >0){                   for (int i = 0; i < 3; i++) { irsend.sendNEC(0x609F48B7,32); delay(40);} //rechts draaien             }                                if(readString.indexOf('a') >0){                   for (int i = 0; i < 3; i++) { irsend.sendNEC(0x609F20DF,32); delay(40);} //preset A             }                              if(readString.indexOf('b') >0){                   for (int i = 0; i < 3; i++) { irsend.sendNEC(0x609FA05F,32); delay(40);} //preset B             }                              if(readString.indexOf('c') >0){                   for (int i = 0; i < 3; i++) { irsend.sendNEC(0x609F609F,32); delay(40);} //preset C             }                              if(readString.indexOf('d') >0){                   for (int i = 0; i < 3; i++) { irsend.sendNEC(0x609FE01F,32); delay(40);} //preset D             }                              if(readString.indexOf('e') >0){                   for (int i = 0; i < 3; i++) { irsend.sendNEC(0x609F10EF,32); delay(40);} //preset E             }                              if(readString.indexOf('f') >0){                   for (int i = 0; i < 3; i++) { irsend.sendNEC(0x609F906F,32); delay(40);} //preset F             }                              if(readString.indexOf('g') >0){                   for (int i = 0; i < 3; i++) { irsend.sendNEC(0x609F50AF,32); delay(40);} //preset G             }                              if(readString.indexOf('h') >0){                   for (int i = 0; i < 3; i++) { irsend.sendNEC(0x609FD02F,32); delay(40);} //preset H             }                              if(readString.indexOf('i') >0){                   for (int i = 0; i < 3; i++) { irsend.sendNEC(0x609F30CF,32); delay(40);} //preset I             }                              if(readString.indexOf('j') >0){                   for (int i = 0; i < 3; i++) { irsend.sendNEC(0x609FB04F,32); delay(40);} //preset J             }                              if(readString.indexOf('u') >0){                   for (int i = 0; i < 3; i++) { irsend.sendNEC(0x609F708F,32); delay(40);} //preset U             }                              if(readString.indexOf('l') >0){                   for (int i = 0; i < 3; i++) { irsend.sendNEC(0x609FF00F,32); delay(40);} //preset L             }                          if(readString.indexOf('y') >0){                   for (int i = 0; i < 3; i++) { irsend.sendNEC(0x609F08F7,32); delay(40);} //initial             }                            if(readString.indexOf('z') >0){                   for (int i = 0; i < 3; i++) { irsend.sendNEC(0x609FC837,32); delay(40);} //memory             }                                                  readString="";           digitalWrite(2,HIGH);           delay(100);           digitalWrite(2,LOW);         }       }     }   } }

const prog_char string_a[] PROGMEM = " ?

I tried to put "const " before all the prog_char string_ .. lines but the error remains. Or is that not what you meant?

Replace prog_char with const char, and do the same for other prog_"datatype" typedefs.

const char string_a[] PROGMEM =

The short answer is that the newer IDE is shipping with a newer avr-gcc toolset and some of the older ways of doing things no longer work. However, there are ways of doing declarations that work with both the new and the old avr-gcc toolset.

A bit more information. Things like prog_char, progmem, PROGMEM, etc.. are not part of Arduino nor the IDE. They are AVR specific and are technically not part of gcc. They are proprietary AVR capabilities provided by AVR libC which is included with the avr version of gcc.

The progmem stuff is kind of a hack that allows using FLASH storage for constant data since the internal AVR h/w architecture does not allow it to use the normal C language constructs for constant data that can be used on other processors like ARM, pic32, x386, 68k, etc... i.e. the AVR couldn't store constant data in flash because its architecture was incompatible with C's notion of address space.

Because the AVR progmem stuff was implemented as kind of hack in the libC library vs being really supported by the compiler, it has some issues particularly with C++, and that is why you get warnings when it is used in C++.

The AVR progmem stuff also played a bit fast and loose with some of the rules.

As avr-gcc has been updated over the years, changes and additional modifications/updates have been made to the actual compiler to better support Harvard architectures like the AVR, which has required that some changes also had to be made to the AVR progmem stuff. As a result some of the earlier progmem definitions have been changed, deprecated, or have been removed. Also some of the syntax that was technically incorrect still worked with the older compilers no longer works with the newer compiler. In fact, many of the examples on the Arduino progmem page were wrong and were in that "technically incorrect but worked" category.

The prog_ data types have been deprecated for quite some time. The Arduino has been shipping old versions of the avr-gcc tools but now with the newer compiler, they no longer work.

--- bill

Thank you so much guys, especially bperrybap for the detailed explanation, that clears up a lot!

I did replace all the prog_char with ‘const char’ and indeed a lot of the errors are no more. I still get one more:

‘error: variable ‘string_table’ must be const in order to be put into read-only section by means of ‘attribute((progmem))’.’

I have no idea what to do for this one. It’s probably this one that needs to change?:

PROGMEM const char *string_table[] =

Any help would be, again, appreciated!

That one is tricky since you want a pointer to an array of "const" pointers to "const" data that is itself a "const" pointer. This kind of stuff is very easy with all the other processors since they support const (you can access the data directly without the indirect table) but is very tricky & messy with AVR given it doesn't support const.

This should work:

PGM_P const string_table[]  PROGMEM =

--- bill

that's absolutely brilliant, works like a charm! Thank you so much!!

This compiles OK:

const char string_a[] PROGMEM = "";

See my page about using PROGMEM:

Nick, In his case, he had an array of const pointers to const data not just a pointer to const data.

--- bill

Yes but I have examples on the linked page. This compiles without errors:

const char string_a[] PROGMEM = "";
const char string_b[] PROGMEM = "";
const char string_c[] PROGMEM = "";
const char string_d[] PROGMEM = "";
const char string_e[] PROGMEM = "";
const char string_f[] PROGMEM = "";
const char string_g[] PROGMEM = "";
const char string_h[] PROGMEM = "";
const char string_i[] PROGMEM = "";
const char string_j[] PROGMEM = "";
const char string_u[] PROGMEM = "";
const char string_l[] PROGMEM = "";
const char string_initial[] PROGMEM = "";
const char string_memory[] PROGMEM = "";
const char string_left[] PROGMEM = "";
const char string_right[] PROGMEM = "";

 const char * const string_table[] PROGMEM =       // change "string_table" name to suit

void setup() { }
void loop() { }

Nick, You just saved my bacon. I use PROGMEM a lot -- always filling up the Mega328 to the brim.

It's that extra "const" that is the key for creating tables in program.

[quote author=Nick Gammon date=1413286146 link=msg=1920458]

const char string_a[] PROGMEM = "";
const char string_b[] PROGMEM = "";

 const char * const string_table[] PROGMEM =   // change "string_table" name to suit


For those searching on this issue --> Here's what I've got (thanks to one of the last lines in your post) that works:

        Pre 1.5.8:    const prog_car mystring[]    PROGMEM = {"...."}
        1.5.8:        const char      mystring[]      PROGMEM = {"...."}
        Pre 1.5.8:    PROGMEM const char * string_table[] = { &s1, &s2...}
        1.5.8:        PGM_P const string_table[] PROGMEM = { &s1, &s2...}
        // For saving pointers to structs
        Pre 1.5.8:    PROGMEM const struct mode * master_mode_table[] = 
        1.5.8:        const struct mode * const   master_mode_table[]  PROGMEM =