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 1008 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
  • mcb1
    0 mcb1 over 9 years ago

    While you have put the strings into Serial.print(F) it still uses lots of memory.

    You could try commenting many of them out just to see, but I suspect that you are running out of memory.

     

    Each library that you use adds more, and some code has a lot of unused variables, routines and other code.

     

    I don't have those libraries so I can't see what figures it comes back with when it compiles.

    This may help you to figure it out

    https://oscarliang.com/check-ram-memory-usage-arduino-optimization/

     

    Mark

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

    Yeah, I'm just not sure.  This is where my being new adds to the challenge.  I found and ran the "avr-size" program, but it didn't tell me anything that the compiler didn't already tell me - namely:

     

    image

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

    This is where my being new adds to the challenge

    We all start somewhere.

    I had a similar issue some time ago, and the final clue was it changed as I added more debug serial outputs to solve it.

     

    I see there are some other answers which may or may not help you.

    Mark

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

    This is where my being new adds to the challenge

    We all start somewhere.

    I had a similar issue some time ago, and the final clue was it changed as I added more debug serial outputs to solve it.

     

    I see there are some other answers which may or may not help you.

    Mark

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Verify Answer
    • Cancel
Children
No Data
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