element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • About Us
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
Arduino
  • Products
  • More
Arduino
Arduino Forum Having trouble combining sketches, and am not sure if it is memory related or something else
  • Blog
  • Forum
  • Documents
  • Quiz
  • Events
  • Polls
  • Files
  • Members
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
Join Arduino to participate - click to join for free!
Actions
  • Share
  • More
  • Cancel
Forum Thread Details
  • State Verified Answer
  • Replies 14 replies
  • Answers 3 answers
  • Subscribers 394 subscribers
  • Views 1010 views
  • Users 0 members are here
  • arduino uno
Related

Having trouble combining sketches, and am not sure if it is memory related or something else

donfrankrice
donfrankrice over 9 years ago

Hi everyone,

 

I am fairly new to Arduino, and a beginner programmer, and could really use another pair of eyes to help me figure out how to dig my way out of a problem.

 

Here's my setup. I have an Arduino Uno, an Ethernet Shield 2, a magnetic window sensor, an HC-SR04 ultrasonic sensor, and an IP camera. I have the ultrasonic sensor pointing at a small box that I have place to simulate a "window".

 

Here's how things are supposed to work. When the magnetic sensor is pulled apart, the "window" is open. The ultrasonic sensor sends out a ping, and if the return is measured to be at least 15cm, the IP camera is accessed to retrieve a still image. This image is saved to the SD card on the Ethernet shield, and then encoded and sent off as an email attachment via SMTP2GO.

 

At present, I have the call to "encode()" commented out (line 251 below). With everything else in place, my sketch uses up 82% program space and 78% dynamic memory. When run, I successfully retrieve and save the image from the IP camera and the email is successfully sent (albeit with a blank attached file - remember, no encoding takes place). That works well. The second that I remove the comments to the call to "encode()", my program space is used up by 84%, and dynamic memory by 81%. This time, running the sketch results in the image failing to save. The file opens and closes, but no data ever gets written. re-comment the call to "encode()", and all is well again.

 

Thinking that this was a memory problem, I started looking into Arduino memory management. I am new to this, so I am not sure that I understand everything. I already have F() placed around my Serial.println strings, but none around my client.println strings. Putting F() around even one of these client.println strings reduces my dynamic memory use by 1% (good!), but when I run the code my image fails to save again (bad!).

 

I have successfully tested each segment of this (window sensor, ultrasonic sensor, camera access, image retrieval, attachment sent as email) in separate sketches.  My challenge has been in combining them all into a single sketch.  Most of it has gone well - and things have only started to go wrong when I tried adding the email portion of this.

 

Can someone please tell me where I am going wrong? Here is my code that I am using, borrowed from several examples found online.

 

#include <SPI.h>
#include <SD.h>
#include <Ethernet2.h>
#include <NewPing.h>

// Arduino pin tied to trigger pin on the ultrasonic sensor.
#define TRIGGER_PIN  8  

// Arduino pin tied to echo pin on the ultrasonic sensor.
#define ECHO_PIN     7  

// Maximum distance we want to ping for (in centimeters). Maximum sensor 
//distance is rated at 400-500cm.
#define MAX_DISTANCE 200 

// window sensor pin
#define WindowPin  6 

//variable to hold the distance to the "window"
int distance;

// NewPing setup of pins and maximum distance.
NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); 

byte mac[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66 };
IPAddress server(192, 168, 1, 27);
IPAddress ip(192, 168, 1, 100);

char mailServer[] = "mail.smtp2go.com";

EthernetClient client;

boolean currentLineIsBlank = true;
File theFile;
File sendFile;

//variable to use for encoding process
static const char cb64[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

void setup() 
{
  Serial.begin(9600);
  Serial.println(F("Starting the serial monitor"));
  pinMode(WindowPin, INPUT_PULLUP);
  
  // disable Ethernet chip
  pinMode(10, OUTPUT);
  digitalWrite(10, HIGH);
  
  Serial.print(F("Initializing SD card..."));

  if (!SD.begin(4)) 
  {
    Serial.println(F(" initialization failed!"));
    return;
  }
  Serial.println(F(" initialization done."));
  
  // start the Ethernet connection:
  if (Ethernet.begin(mac) == 0) 
  {
    Serial.println(F("Failed to configure Ethernet using DHCP"));
    // try to congifure using IP address instead of DHCP:
    Ethernet.begin(mac, ip);
  }
  // give the Ethernet shield a second to initialize:
  delay(1000);

 // print your local IP address:
  Serial.println(Ethernet.localIP());  

}

void loop() 
{
  //take a read of the WindowPin.  If it reads HIGH, the window is open,
  //and a message can be displayed as such
  if(digitalRead(WindowPin) == HIGH)
  {
    Serial.println(F("the window is open. check to see if person is inside or outside"));
    
    // Wait 50ms between pings (about 20 pings/sec). 29ms should be the 
    //shortest delay between pings.
    delay(50);                     
    Serial.print(F("Ping: "));
    
    // Send ping, get distance in cm and print result (0 = outside set distance range)
    distance = sonar.ping_cm();
    Serial.print(distance); 
    Serial.print(F("cm"));
    
    //if the distance to the "window" is less than 15cm, indicate that it was
    //opened from inside. Otherwise, insicate that it was opened from outside
    if(distance <15)
    {
      Serial.println(F(" --opened from inside"));
      Serial.println();
    }
    else
    {
      Serial.println(F(" --opened from outside"));
      Serial.println(F("Let's take a picture"));
      
     
        Serial.println(F("connecting to camera..."));
      
        // if you get a connection, report back via serial:
        if (client.connect(server, 80)) 
        {
          Serial.println(F("connected"));
          // Make a HTTP request:
          client.println("GET /image.jpg");
          client.println("Authorization: Basic Y=");
          client.println("Host: 192.168.1.27");
          //client.println("Connection: close");
          client.println();
          delay(1000);
        }
        else 
        {
          // kf you didn't get a connection to the server:
          Serial.println(F("connection failed"));
        }
        
   // open the file for writing
  Serial.println(F("Creating file."));
  theFile = SD.open("pic.jpg", FILE_WRITE);  // change file name to write to here
  if (!theFile) {
    Serial.println(F("Could not create file"));
    while (1);
  }
  // from the server, read them and print them:
  while (client.available()) {
    char c = client.read();
    if (c == '\n' && currentLineIsBlank) {
      // end of HTTP header, now save requested file
      while (client.connected()) {
        // stay in this loop until the file has been received
        if (client.available()) {
          c = client.read();  // get file byte
          Serial.print(c);
          theFile.print(c);   // save file byte
        }
      }
    }
    // detect the end of the incoming HTTP header
    if (c == '\n') {
      // starting a new line
      currentLineIsBlank = true;
    }
    else if (c != '\r') {
      // got a character on the current line
      currentLineIsBlank = false;
    }
  }

  // if the server's disconnected, stop the client:
  if (!client.connected()) {
    Serial.println();
    Serial.println(F("disconnecting."));
    client.stop();
    theFile.close();
    Serial.println(F("Finished writing to file"));
    
    if(sendEmail()) Serial.println(F("Email Sent"));
      else Serial.println(F("Email Failed"));
    
    while(true);
    
    // do nothing forevermore:
    //while (true);
  }
  }
  
  //delay for 2 seconds, to avoid incessant scrolling
    delay(2000);
  }
  
  //If the sensor reads LOW, the window is closed, and a message can be
  //displayed as such.  No need to involve the ultrasonic sensor
  else
  {
    Serial.println(F("Window is closed. No need to check distance"));
    
    //delay for 2 seconds, to avoid incessant scrolling
    delay(2000);
  }
  
}


byte sendEmail(){
  byte thisByte = 0;
  byte respCode;
  
  if(client.connect(mailServer, 80) == 1){
    Serial.println(F("Connected"));
  }
  else {
    Serial.println(F("Connection Failed"));
    return 0;
  }
  if(!eRcv()) return 0;

  Serial.println(F("Sending Hello"));
//replace 1.2.3.4 with your Arduino's ip**************************
  client.println("EHLO");
  if(!eRcv()) return 0;

  Serial.println(F("Sending authorizes login"));
  client.println("auth login");
  if(!eRcv()) return 0;

  Serial.println(F("Sending User"));
//Change to your base64 encoded user**************************
  client.println("Y=");
  if(!eRcv()) return 0;

  Serial.println(F("Sending Password"));
//change to your base64 encoded password**************************
  client.println("Y=");
  if(!eRcv()) return 0;

//change to your email address (sender)**************************
  Serial.println(F("Sending From"));
  client.println("MAIL From: <ME@gmail.com>");
  if(!eRcv()) return 0;

//change to recipient address**************************
  Serial.println(F("Sending To"));
  client.println("RCPT To: <YOU@gmail.com>");
  if(!eRcv()) return 0;
  Serial.println(F("Sending DATA"));
  client.println("DATA");
  if(!eRcv()) return 0;
  Serial.println(F("Sending email"));

//change to recipient address**************************
  client.println("To: You <YOU@gmail.com>");

//change to your address**************************
  client.println("From: Me <ME@gmail.com>");
  client.println("Subject: Sent from Donny's Arduino");
  
//Start of Attach File
  sendFile =SD.open("pic.jpg",FILE_READ);
  client.print("Content-Type: image/jpg; name=\"pic.jpg\"\r\n");
  client.write("Content-Disposition: attachment; filename=pic.jpg\r\n");
  client.print("Content-Transfer-Encoding: base64\r\n\r\n");
  
  //encode();
  sendFile.close();
//End of Attach File

  client.print("\r\n.\r\nQUIT\n");
  if(!eRcv()) return 0;
  client.stop();
  Serial.println(F("disconnected"));
  return 1;
}

byte eRcv(){
  byte respCode;
  byte thisByte;
  int loopCount = 0;
  while(!client.available()){
    delay(1);
    loopCount++;
    // if nothing received for 10 seconds, timeout
    if(loopCount > 10000) {
      client.stop();
      Serial.println(F("\r\nTimeout"));
      return 0;
    }
  }
  respCode = client.peek();
  while(client.available()){ 
    thisByte = client.read();   
    Serial.write(thisByte);
  }
  if(respCode >= '4'){
    efail();
    return 0; 
  }
  return 1;
}

void efail(){
  byte thisByte = 0;
  int loopCount = 0;
  client.println(F("QUIT"));
  while(!client.available()) {
    delay(1);
    loopCount++;
    // if nothing received for 10 seconds, timeout
    if(loopCount > 10000) {
      client.stop();
      Serial.println(F("\r\nTimeout"));
      return;
    }
  }
  while(client.available()){ 
    thisByte = client.read();   
    Serial.write(thisByte);
  }
  client.stop();
  Serial.println(F("isconnected"));
}

void encodeblock(unsigned char in[3],unsigned char out[4],int len) {
  out[0]=cb64[in[0]>>2]; out[1]=cb64[((in[0]&0x03)<<4)|((in[1]&0xF0)>>4)];
  out[2]=(unsigned char) (len>1 ? cb64[((in[1]&0x0F)<<2)|((in[2]&0xC0)>>6)] : '=');
  out[3]=(unsigned char) (len>2 ? cb64[in[2]&0x3F] : '=');
}

void encode() {
  unsigned char in[3],out[4];
  int i,len,blocksout=0;
  while (sendFile.available()!=0) {
    len=0;
    for (i=0;i<3;i++){
      in[i]=(unsigned char) sendFile.read();
      if (sendFile.available()!=0) len++;
      else in[i]=0;
    }
    if (len){
      encodeblock(in,out,len);
      for(i=0;i<4;i++) client.write(out[i]);
        blocksout++;
    }
    if (blocksout>=19||sendFile.available()==0){
      if (blocksout) client.print("\r\n");  blocksout=0;
    }
  }
}

 

 

Thanks for your help in advance.  I really appreciate it!

 

Donny

  • Sign in to reply
  • Cancel
Parents
  • Former Member
    0 Former Member over 9 years ago

    I was able to reduce the dynamic memory from 81% to 68% with the PSTR and strcpy_P that I mentioned.

    The buffer increases the dynamic memory usage, but it is a single buffer that is used over and over again.

     

    // commonly used global buffer
    char buffer[80];     // I hope that 80 is enough
    ...
    
    
      // Replace every client.print with PSTR and the buffer.
      // client.println("GET /image.jpg");
      // Is a println with \r\n or just \n ?
      strcpy_P( buffer, PSTR( "GET /image.jpg\r\n"));
      client.write( buffer);

     

    The 'F()' and 'PSTR()' and PROGMEM do the same thing. They put the text in flash memory. The .print() wants a 'F()' and the strcpy_P() wants a 'PSTR()'. It should be the same of course, but someone messed up and created an extra macro with a slightly different pointer definition.

     

    I tried what mcb1 wrote, and removed every call to the Serial library with a 'DEBUG' define. That should release the buffers inside the Serial library, but it didn't. The ram usage was only reduced by 1 or 2%. Perhaps the libraries have calls to the Serial library ?

     

    Peter Oakes uses PROGMEM and a 'debug' define and a global common buffer. That is the best way to do it, and I use that myself for larger projects. The only difference here is that I used the PSTR with the text at that place in the code. It is all the same, you can use whatever you like more.

     

    P.S.: You gonna need a Arduino Mega 2560 in the end anyway image

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Verify Answer
    • Reject Answer
    • Cancel
Reply
  • Former Member
    0 Former Member over 9 years ago

    I was able to reduce the dynamic memory from 81% to 68% with the PSTR and strcpy_P that I mentioned.

    The buffer increases the dynamic memory usage, but it is a single buffer that is used over and over again.

     

    // commonly used global buffer
    char buffer[80];     // I hope that 80 is enough
    ...
    
    
      // Replace every client.print with PSTR and the buffer.
      // client.println("GET /image.jpg");
      // Is a println with \r\n or just \n ?
      strcpy_P( buffer, PSTR( "GET /image.jpg\r\n"));
      client.write( buffer);

     

    The 'F()' and 'PSTR()' and PROGMEM do the same thing. They put the text in flash memory. The .print() wants a 'F()' and the strcpy_P() wants a 'PSTR()'. It should be the same of course, but someone messed up and created an extra macro with a slightly different pointer definition.

     

    I tried what mcb1 wrote, and removed every call to the Serial library with a 'DEBUG' define. That should release the buffers inside the Serial library, but it didn't. The ram usage was only reduced by 1 or 2%. Perhaps the libraries have calls to the Serial library ?

     

    Peter Oakes uses PROGMEM and a 'debug' define and a global common buffer. That is the best way to do it, and I use that myself for larger projects. The only difference here is that I used the PSTR with the text at that place in the code. It is all the same, you can use whatever you like more.

     

    P.S.: You gonna need a Arduino Mega 2560 in the end anyway image

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Verify Answer
    • Reject Answer
    • Cancel
Children
  • mcb1
    0 mcb1 over 9 years ago in reply to Former Member

    I tried what mcb1 wrote, and removed every call to the Serial library with a 'DEBUG' define.

    I was thinking that you might be able to reduce the size of the 'info' messages.

    ie  Serial.println(F("the window is open. check to see if person is inside or outside"));

    could be reduced to  Serial.println(F("window open"));

     

    it would still have the same meaning but reduce the characters in memory.

     

    Mark

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Verify Answer
    • Cancel
  • Former Member
    0 Former Member over 9 years ago in reply to mcb1

    Yes, but program space is not the problem (yet). I was only focusing on the dynamic memory (ram) usage.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Verify Answer
    • Cancel
  • donfrankrice
    0 donfrankrice over 9 years ago in reply to Former Member

    Hi Koepel,

     

    I had a few minutes this evening to look at these posts again, and I would like to make sure that I am understanding the usage of strcpy_P and PSTR correctly.

     

    Does this original code:

     

    if (client.connect(server, 80)) 
    {
      Serial.println(F("connected"));
      // Make a HTTP request:
              
      client.println("GET /image.jpg");
      client.println("Authorization: Basic YWRtaW46YXVndXN0MTA=");
      client.println("Host: 192.168.1.27");
      //client.println("Connection: close");
      client.println();
      delay(1000);
    }
    else 
    {
      // kf you didn't get a connection to the server:
      Serial.println(F("connection failed"));
    }

     

    become this code:

     

    if (client.connect(server, 80)) 
    {
      Serial.println(F("connected"));
      // Make a HTTP request:
            
      strcpy_P(buffer, PSTR("GET /image.jpg\r\n"));
      client.write(buffer);
              
      strcpy_P(buffer, PSTR("Authorization: Basic YWRtaW46YXVndXN0MTA=\r\n"));
      client.write(buffer);
              
      strcpy_P(buffer, PSTR("Host: 192.168.1.27\r\n"));
      client.write(buffer);
              
      //client.println("Connection: close");
      client.println();
      delay(1000);
    }
    else 
    {
      // if you didn't get a connection to the server:
      Serial.println(F("connection failed"));
    }

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Verify Answer
    • Cancel
  • donfrankrice
    0 donfrankrice over 9 years ago in reply to donfrankrice

    OK, so I think I answered my own question.  I replaced all of the code like above, which resulted in dynamic memory usage going down to 63%:

     

    #include <SPI.h>
    #include <SD.h>
    #include <Ethernet2.h>
    #include <NewPing.h>
    
    
    
    
    // Arduino pin tied to trigger pin on the ultrasonic sensor.
    #define TRIGGER_PIN  8  
    
    
    // Arduino pin tied to echo pin on the ultrasonic sensor.
    #define ECHO_PIN     7  
    
    
    // Maximum distance we want to ping for (in centimeters). Maximum sensor 
    //distance is rated at 400-500cm.
    #define MAX_DISTANCE 200 
    
    
    // window sensor pin
    #define WindowPin  6 
    
    
    //variable to hold the distance to the "window"
    int distance;
    
    
    // NewPing setup of pins and maximum distance.
    NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); 
    
    
    byte mac[] = { 0x90, 0xA2, 0xDA, 0x10, 0x7A, 0x87 };
    IPAddress server(192, 168, 1, 27);
    IPAddress ip(192, 168, 1, 100);
    
    
    char mailServer[] = "mail.smtp2go.com";
    
    
    EthernetClient client;
    
    
    boolean currentLineIsBlank = true;
    File theFile;
    File sendFile;
    
    
    //variable to use for encoding process
    static const char cb64[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    
    
    char buffer[80];
    
    
    void setup() 
    {
      Serial.begin(9600);
      Serial.println("Starting the serial monitor");
      pinMode(WindowPin, INPUT_PULLUP);
      
      //****************************************
      //new on 8/31
      // disable Ethernet chip
      pinMode(10, OUTPUT);
      digitalWrite(10, HIGH);
      
      Serial.print(F("Initializing SD card..."));
    
    
      if (!SD.begin(4)) 
      {
        Serial.println(F(" initialization failed!"));
        return;
      }
      Serial.println(F(" initialization done."));
      
      //*****************************************
      
      
      // start the Ethernet connection:
      if (Ethernet.begin(mac) == 0) 
      {
        Serial.println(F("Failed to configure Ethernet using DHCP"));
        // no point in carrying on, so do nothing forevermore:
        // try to congifure using IP address instead of DHCP:
        Ethernet.begin(mac, ip);
      }
      // give the Ethernet shield a second to initialize:
      delay(1000);
    
    
      // print your local IP address:
      Serial.println(Ethernet.localIP());  
    
    
    }
    
    
    void loop() 
    {
      //take a read of the WindowPin.  If it reads HIGH, the window is open,
      //and a message can be displayed as such
      if(digitalRead(WindowPin) == HIGH)
      {
        Serial.println(F("the window is open. check to see if person is inside or outside"));
        
        // Wait 50ms between pings (about 20 pings/sec). 29ms should be the 
        //shortest delay between pings.
        delay(50);                     
        Serial.print(F("Ping: "));
        
        // Send ping, get distance in cm and print result (0 = outside set distance range)
        distance = sonar.ping_cm();
        Serial.print(distance); 
        Serial.print(F("cm"));
        
        //if the distance to the "window" is less than 15cm, indicate that it was
        //opened from inside. Otherwise, insicate that it was opened from outside
        if(distance <15)
        {
          Serial.println(F(" --opened from inside"));
          Serial.println();
        }
        else
        {
          Serial.println(F(" --opened from outside"));
          Serial.println(F("Let's take a picture"));
          
         
          Serial.println(F("connecting to camera..."));
          
          // if you get a connection, report back via serial:
          if (client.connect(server, 80)) 
          {
            Serial.println(F("connected"));
            // Make a HTTP request:
            
            strcpy_P(buffer, PSTR("GET /image.jpg\r\n"));
            client.write(buffer);
              
            strcpy_P(buffer, PSTR("Authorization: Basic YWRtaW46YXVndXN0MTA=\r\n"));
            client.write(buffer);
              
            strcpy_P(buffer, PSTR("Host: 192.168.1.27\r\n"));
            client.write(buffer);
              
            //client.println("Connection: close");
            client.println();
            delay(1000);
          }
          else 
          {
            // if you didn't get a connection to the server:
            Serial.println(F("connection failed"));
          }
            
          // open the file for writing
        Serial.println(F("Creating file."));
      theFile = SD.open("pic.jpg", FILE_WRITE);  // change file name to write to here
      if (!theFile) {
        Serial.println(F("Could not create file"));
        while (1);
      }
      // from the server, read them and print them:
      while (client.available()) {
        char c = client.read();
        if (c == '\n' && currentLineIsBlank) {
          // end of HTTP header, now save requested file
          while (client.connected()) {
            // stay in this loop until the file has been received
            if (client.available()) {
              c = client.read();  // get file byte
              Serial.print(c);
              theFile.print(c);   // save file byte
            }
          }
        }
        // detect the end of the incoming HTTP header
        if (c == '\n') {
          // starting a new line
          currentLineIsBlank = true;
        }
        else if (c != '\r') {
          // got a character on the current line
          currentLineIsBlank = false;
        }
      }
    
    
      // if the server's disconnected, stop the client:
      if (!client.connected()) {
        Serial.println();
        Serial.println(F("disconnecting."));
        client.stop();
        theFile.close();
        Serial.println(F("Finished writing to file"));
        
        if(sendEmail()) Serial.println(F("Email Sent"));
          else Serial.println(F("Email Failed"));
        
        while(true);
        
        // do nothing forevermore:
        //while (true);
      }
       
      
    
    
      }
      
      //delay for 2 seconds, to avoid incessant scrolling
        delay(2000);
      }
      
      //If the sensor reads LOW, the window is closed, and a message can be
      //displayed as such.  No need to involve the ultrasonic sensor
      else
      {
        Serial.println(F("Window is closed. No need to check distance"));
        
        //delay for 2 seconds, to avoid incessant scrolling
        delay(2000);
      }
      
    }
    
    
    byte sendEmail(){
      byte thisByte = 0;
      byte respCode;
      
      if(client.connect(mailServer, 80) == 1){
        Serial.println(F("Connected"));
      }
      else {
        Serial.println(F("Connection Failed"));
        return 0;
      }
      if(!eRcv()) return 0;
    
    
      Serial.println(F("Sending Hello"));
    //replace 1.2.3.4 with your Arduino's ip**************************
      strcpy_P(buffer, PSTR("EHLO\r\n"));
      client.write(buffer);
      if(!eRcv()) return 0;
    
    
      Serial.println(F("Sending authorizes login"));
      strcpy_P(buffer, PSTR("auth login\r\n"));
      client.write(buffer);
      if(!eRcv()) return 0;
    
    
      Serial.println(F("Sending User"));
    //Change to your base64 encoded user**************************
      strcpy_P(buffer, PSTR("Y29tcDQ0NC5kb25mcmFua3JpY2U=\r\n"));
      client.write(buffer);
      if(!eRcv()) return 0;
    
    
      Serial.println(F("Sending Password"));
    //change to your base64 encoded password**************************
      strcpy_P(buffer, PSTR("YXJkdWlub1J1bGVzIQ==\r\n"));
      client.write(buffer);
      if(!eRcv()) return 0;
    
    
    //change to your email address (sender)**************************
      Serial.println(F("Sending From"));
      strcpy_P(buffer, PSTR("MAIL From: <donny.frankrice@gmail.com>\r\n"));
      client.write(buffer);
      if(!eRcv()) return 0;
    
    
    //change to recipient address**************************
      Serial.println(F("Sending To"));
      strcpy_P(buffer, PSTR("RCPT To: <comp444.donfrankrice@gmail.com>\r\n"));
      client.write(buffer);
      if(!eRcv()) return 0;
      
      Serial.println(F("Sending DATA"));
      strcpy_P(buffer, PSTR("DATA\r\n"));
      client.write(buffer);
      if(!eRcv()) return 0;
      
      Serial.println(F("Sending email"));
      //change to recipient address**************************
      strcpy_P(buffer, PSTR("To: You <comp444.donfrankrice@gmail.com>\r\n"));
      client.write(buffer);
    
    
      //change to your address**************************
      strcpy_P(buffer, PSTR("From: Me <donny.frankrice@gmail.com>\r\n"));
      client.write(buffer);
      
      strcpy_P(buffer, PSTR("Subject: Sent from Donny's Arduino\r\n"));
      client.write(buffer);
      
    //****************************************************
    //Start of Attach File
      sendFile =SD.open("pic.jpg",FILE_READ);
      
      strcpy_P(buffer, PSTR("Content-Type: image/jpg; name=\"pic.jpg\"\r\n\r\n"));
      client.write(buffer);
      
      client.write("Content-Disposition: attachment; filename=pic.jpg\r\n");
      
      strcpy_P(buffer, PSTR("Content-Transfer-Encoding: base64\r\n\r\n\r\n"));
    
      
    //  encode();
      sendFile.close();
    //End of Attach File
    //****************************************************
      client.print("\r\n.\r\nQUIT\n");
      if(!eRcv()) return 0;
      client.stop();
      Serial.println(F("disconnected"));
      return 1;
    }
    
    
    byte eRcv(){
      byte respCode;
      byte thisByte;
      int loopCount = 0;
      while(!client.available()){
        delay(1);
        loopCount++;
        // if nothing received for 10 seconds, timeout
        if(loopCount > 10000) {
          client.stop();
          Serial.println(F("\r\nTimeout"));
          return 0;
        }
      }
      respCode = client.peek();
      while(client.available()){ 
        thisByte = client.read();   
        Serial.write(thisByte);
      }
      if(respCode >= '4'){
        efail();
        return 0; 
      }
      return 1;
    }
    
    
    void efail(){
      byte thisByte = 0;
      int loopCount = 0;
      
      strcpy_P(buffer, PSTR("QUIT\r\n"));
      client.write(buffer);
      
      while(!client.available()) {
        delay(1);
        loopCount++;
        // if nothing received for 10 seconds, timeout
        if(loopCount > 10000) {
          client.stop();
          Serial.println(F("\r\nTimeout"));
          return;
        }
      }
      while(client.available()){ 
        thisByte = client.read();   
        Serial.write(thisByte);
      }
      client.stop();
      Serial.println(F("isconnected"));
    }
    
    
    void encodeblock(unsigned char in[3],unsigned char out[4],int len) {
      out[0]=cb64[in[0]>>2]; out[1]=cb64[((in[0]&0x03)<<4)|((in[1]&0xF0)>>4)];
      out[2]=(unsigned char) (len>1 ? cb64[((in[1]&0x0F)<<2)|((in[2]&0xC0)>>6)] : '=');
      out[3]=(unsigned char) (len>2 ? cb64[in[2]&0x3F] : '=');
    }
    
    
    void encode() {
      unsigned char in[3],out[4];
      int i,len,blocksout=0;
      while (sendFile.available()!=0) {
        len=0;
        for (i=0;i<3;i++){
          in[i]=(unsigned char) sendFile.read();
          if (sendFile.available()!=0) len++;
          else in[i]=0;
        }
        if (len){
          encodeblock(in,out,len);
          for(i=0;i<4;i++) client.write(out[i]);
            blocksout++;
        }
        if (blocksout>=19||sendFile.available()==0){
          if (blocksout) client.print("\r\n");  blocksout=0;
        }
      }
    }

     

     

    I won't be able to try the encode() function tonight, though, as we're going out.  I'm hoping it will work better now that I have a lot of extra memory to work with!  We'll know more tomorrow.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Verify Answer
    • Cancel
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2025 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube