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 <avr/pgmspace.h>.

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

Any ideas?
Thanks!

Jens

Code:

/*
DATE: 17-06-2014
PROGRAMMING: JENS VANHOOF
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.
*/
#include <avr/pgmspace.h>
#include <SPI.h>
#include <Ethernet.h>
#include <IRremote.h>


prog_char string_a[] PROGMEM = "<input type=submit value=A style=width:100px;height:45px onClick=location.href='/?a'>";
prog_char string_b[] PROGMEM = "<input type=submit value=B style=width:100px;height:45px onClick=location.href='/?b'>";
prog_char string_c[] PROGMEM = "<input type=submit value=C style=width:100px;height:45px onClick=location.href='/?c'>";
prog_char string_d[] PROGMEM = "<input type=submit value=D style=width:100px;height:45px onClick=location.href='/?d'>";
prog_char string_e[] PROGMEM = "<input type=submit value=E style=width:100px;height:45px onClick=location.href='/?e'>";
prog_char string_f[] PROGMEM = "<input type=submit value=F style=width:100px;height:45px onClick=location.href='/?f'>";
prog_char string_g[] PROGMEM = "<input type=submit value=G style=width:100px;height:45px onClick=location.href='/?g'>";
prog_char string_h[] PROGMEM = "<input type=submit value=H style=width:100px;height:45px onClick=location.href='/?h'>";
prog_char string_i[] PROGMEM = "<input type=submit value=I style=width:100px;height:45px onClick=location.href='/?i'>";
prog_char string_j[] PROGMEM = "<input type=submit value=J style=width:100px;height:45px onClick=location.href='/?j'>";
prog_char string_u[] PROGMEM = "<input type=submit value=U style=width:100px;height:45px onClick=location.href='/?u'>";
prog_char string_l[] PROGMEM = "<input type=submit value=L style=width:100px;height:45px onClick=location.href='/?l'>";
prog_char string_initial[] PROGMEM = "<input type=submit value=Initial style=width:200px;height:45px onClick=location.href='/?y'>";
prog_char string_memory[] PROGMEM = "<input type=submit value=Memory style=width:200px;height:45px onClick=location.href='/?z'>";
prog_char string_left[] PROGMEM = "<input type=submit value=LEFT style=width:200px;height:90px onClick=location.href='/?8'>";
prog_char string_right[] PROGMEM = "<input type=submit value=RIGHT style=width:200px;height:90px onClick=location.href='/?9'>";



PROGMEM const char *string_table[] = 	   // change "string_table" name to suit
{   
  string_a,
  string_b,
  string_c,
  string_d,
  string_e,
  string_f,
  string_g,
  string_h,
  string_i,
  string_j,
  string_u,
  string_l,
 string_initial,
string_memory,
string_left,
string_right};
  
  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);
  server.begin();
pinMode(2,OUTPUT);
digitalWrite(2,HIGH);
delay(2000);
digitalWrite(2,LOW);
  //enable serial data print 
  Serial.begin(9600); 
  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 = client.read();

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

          //store characters to string 
          readString += c; 
          //Serial.print(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();

          client.println("<HTML>");
          client.println("<HEAD>");
          client.println("<TITLE>EuroLinx AR-500 Antenna Rotator</TITLE>");
          client.println("</HEAD>");
          client.println("<BODY>");

          client.println("<H1>AR-500 Antenna Rotator</H1>");
          
        
          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("<p></p>");
         client.print("(c) EuroLinx 2014, written by Jens Vanhoof.");
          
          
          client.println("</BODY>");
          client.println("</HTML>");
 
          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 = "<input type=submit value=A style=width:100px;height:45px onClick=location.href='/?a'>";
...

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 = "<input type=submit value=A style=width:100px;height:45px onClick=location.href='/?a'>";
const char string_b[] PROGMEM = "<input type=submit value=B style=width:100px;height:45px onClick=location.href='/?b'>";
const char string_c[] PROGMEM = "<input type=submit value=C style=width:100px;height:45px onClick=location.href='/?c'>";
const char string_d[] PROGMEM = "<input type=submit value=D style=width:100px;height:45px onClick=location.href='/?d'>";
const char string_e[] PROGMEM = "<input type=submit value=E style=width:100px;height:45px onClick=location.href='/?e'>";
const char string_f[] PROGMEM = "<input type=submit value=F style=width:100px;height:45px onClick=location.href='/?f'>";
const char string_g[] PROGMEM = "<input type=submit value=G style=width:100px;height:45px onClick=location.href='/?g'>";
const char string_h[] PROGMEM = "<input type=submit value=H style=width:100px;height:45px onClick=location.href='/?h'>";
const char string_i[] PROGMEM = "<input type=submit value=I style=width:100px;height:45px onClick=location.href='/?i'>";
const char string_j[] PROGMEM = "<input type=submit value=J style=width:100px;height:45px onClick=location.href='/?j'>";
const char string_u[] PROGMEM = "<input type=submit value=U style=width:100px;height:45px onClick=location.href='/?u'>";
const char string_l[] PROGMEM = "<input type=submit value=L style=width:100px;height:45px onClick=location.href='/?l'>";
const char string_initial[] PROGMEM = "<input type=submit value=Initial style=width:200px;height:45px onClick=location.href='/?y'>";
const char string_memory[] PROGMEM = "<input type=submit value=Memory style=width:200px;height:45px onClick=location.href='/?z'>";
const char string_left[] PROGMEM = "<input type=submit value=LEFT style=width:200px;height:90px onClick=location.href='/?8'>";
const char string_right[] PROGMEM = "<input type=submit value=RIGHT style=width:200px;height:90px onClick=location.href='/?9'>";


 const char * const string_table[] PROGMEM = 	   // change "string_table" name to suit
{   
  string_a,
  string_b,
  string_c,
  string_d,
  string_e,
  string_f,
  string_g,
  string_h,
  string_i,
  string_j,
  string_u,
  string_l,
  string_initial,
  string_memory,
  string_left,
  string_right
};

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.

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 =

[/code]