Feasibility check: programming Arduino MEGA 2560 with Arduino Uno, NO PC


I am thinking about a way to remotely deliver firmware updates. This is not going to be an experiment, but rather a valuable feature for my dozens of Arduino MEGA 2560 R3 based data loggers working in remote areas that we have to spend hours of drive to get to in case of firmware update.

Question: Is there any way to program an Arduino MEGA 2560 with an Arduino Uno (or with MEGA 2560)?

I'm not concerned about how to get the firmware to the programming Arduino at this stage, just whether it can be done.

What I know: There is an option in Arduino IDE to program arduino using another Arduino. I have not tried it yet, but it relies on a PC and I need the Arduino to act alone. So this is not my solution.

This might solve my problem. There is a sample program in Arduino IDE called Arduino_ISP but there are very few comments. The code is not understandable, although I can see the code was taken in from Serial port. So in principle I can use an XBee to deliver the code. But I don't know the overhead, that may not be included in the .HEX and needs to be done or sent to the target. The code seems to make Arduino a slave/state machine of some sort, taking commands. I don't know how the master (PC) should behave to get the target programmed. Here I need help.

Can some expert point me into the correct direction? I can read and try things if you give me something to start with. Thank you!

Is there any way to program an Arduino MEGA 2560 with an Arduino Uno (or with MEGA 2560)?

If the Arduino MEGA 2560 R3 supports ICSP i don´t see a reason why it it shouldn´t work.

Arduino_ISP is using ICSP but you need a wire connection. If you want to do that remotely you need to add a wireless transfer module (Rfid e.g.) and transmit the .hex file wirelessly but you will need to alter Arduino_ISP to be able to receive .hex filed wireless and use a second processor on your board which receives the .hex and transmits it via ICSP to your Mega 2560.

That's my intent. I will have a second arduino with xbee wifi to 1) Receive firmware update, store in SD card, check for integrity, and update main arduino when appropriate 2) Power cycle wifi hotspot in case internet connection is lost for a predetermined amount of time 3) xbee wifi can also be controlled by etherios device cloud so I can remotely power cycle main arduino data logger, camera, another device, except for the hotspot.

I'm just trying to learn how to programmatically flash sketch to arduino via ICSP when the second arduino has a new firmware. Any references you can suggest me read?

how to programmatically flash sketch to arduino via ICSP

Have a look at Tiny_ISP or look here http://en.wikipedia.org/wiki/In-circuit_serial_programming ?

Check Nick's programmer from SD card http://www.gammon.com.au/forum/?id=11638

CrossRoads: Check Nick's programmer from SD card http://www.gammon.com.au/forum/?id=11638

Thanks! Karma! That was what I needed. Unfortunately that forum only allows administrators to post. I'll PM Nick to see if I can ask him a couple of questions.


If you are reading this, could you give me some help on the loading .hex file from sd card post on your forum?


My pins 4-7 are used so I want to switch to analog pins 0-3. How do I change your code (PIND into what)?

// bit banged SPI pins
#ifdef __AVR_ATmega2560__
  // Atmega2560
  const byte MSPIM_SCK = 4;  // port G bit 5
  const byte MSPIM_SS  = 5;  // port E bit 3
  const byte BB_MISO   = 6;  // port H bit 3
  const byte BB_MOSI   = 7;  // port H bit 4
  // Atmega328
  const byte MSPIM_SCK = 4;  // Change to A0 port D bit 4
  const byte MSPIM_SS  = 5;  //  Change to A1 port D bit 5
  const byte BB_MISO   = 6;  //  Change to A2 port D bit 6
  const byte BB_MOSI   = 7;  //  Change to A3 port D bit 7

// for fast port access
#ifdef __AVR_ATmega2560__
  // Atmega2560
  const byte BB_SCK_BIT = 5;
  const byte BB_MISO_BIT = 3;
  const byte BB_MOSI_BIT = 4;
  // Atmega328
  #define BB_MISO_PORT PIND  //<- How to change?
  #define BB_MOSI_PORT PORTD // <-change to PORTC
  #define BB_SCK_PORT PORTD // <-change to PORTC
  const byte BB_SCK_BIT = 4; //<- change to 0
  const byte BB_MISO_BIT = 6; //<- change to 2
  const byte BB_MOSI_BIT = 7; //<- change to 3

I am also not sure about how this program affects the bootloader in the FLASH. From the .HEX files I generated, address starts from 0000. From your post, if address starts from zero, then after upload the code starts from 0000, that means the bootloader is not working (if not erased altogether). Am I correct?

I tried to send you PM but I was blocked. I didn’t know one could do that. Anyway, great work! I’ll go through it alone if I have to.

Thank you!

Analog pins are PINC and PORTC A0 is 14, A1 is 15, A2 is 16, A3 is 17, A4 is 18, A5 is 19

Thank you CR! I didn't know what the PINC or PIND defs are. What is the right place to learn their definitions?

BTW, fingers crossed that Nick will see this post. I tried to PM him but I was blocked. Long code to digest alone, if I want to integrate it together with an HTTP client to GET the firmware from our servers.

It would be very useful if I can actually finish this little project and post it somewhere. Anyone using Ethernet or wifi in their project can add a second arduino and do remote firmware update.

What is the right place to learn their definitions?

The datasheet. Really liudr, you are coming across as quite the newbie here!

Three I/O memory address locations are allocated for each port, one each for the Data Register – PORTx, Data Direction Register – DDRx, and the Port Input Pins – PINx. The Port Input Pins I/O location is read only, while the Data Register and the Data Direction Register are read/write. However, writing a logic one to a bit in the PINx Register, will result in a toggle in the corresponding bit in the Data Register. In addition, the Pull-up Disable – PUD bit in MCUCR disables the pull-up function for all pins in all ports when set.

Thanks. Frankly, I don't use registers at all. Use to be a fan of registers when I was half my age. Most of my projects have been putting different functional parts together and make them work together, like data loggers, lcd keypad panels etc.

So I got Nick's code working on alternative pins. But just as I suspected, the bootloader is gone now. I'm reading the spec sheet. It seems the chip erase erases the entire FLASH.

Am I understanding this right? IF I use an ISP, Arduino IDE tells avrdude to do erase the FLASH, upload the sketch and then the bootloader. This is the only way that makes sense to me. I'll combine the sketch and bootloader to see what happens.

File:Upload using Programmer wipes out the bootloader, yes, and sketch starts immediately after reset.

I did some more tests, combining sketch hex and bootloader hex. It uploaded the combined hex fine but the program insisted that there is no bootloader and set the High fuse to run code from 0000. Stubborn program won't allow me to change high fuse from D9 (run from 0000) to D8 (run from 256K-8K), saying that I was going to disable SPIEN, no way. D enables it. No go.

I need the bootloader when I'm flashing manually with XLoader or arduino IDE.

I had to only flash the bootloader, no sketch and the program decided an HFuse=D8 by itself, good. I may have to think of other ways. Chopping this program may take too long. All its text interface is useless to me. I'm trying to programmatically flash firmware without human interaction. I'll see how this goes. I want the end result to be a function call flash_firmware(char * file_name). No need to mess with lock bits or fuse bits. The function recognizes which chip it is and flashes the firmware and then the right bootloader.

BTW, all my experience with x86 assembly from 1990's was not wasted. I was able to understand the intel HEX format and its CS:IP and 16 bit shift and addressing with a particular record type called start segment address, on wiki. Without all that background, I would have to spend a bit more time :)