Pages: [1]   Go Down
Author Topic: Dedicated sketch uploader/installer  (Read 817 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 0
Posts: 29
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hey guys,
So, I'm a complete idiot when it comes to more than basic Arduino programming, but trying to dive in deeper. For a particular application I have in mind, I want to give end users the ability to easily edit a number of variables, so that they can define what serial strings are sent when a given button is pressed.

Can anybody offer guidance on how to create a standalone editor/loader that would let them either edit these strings directly in said program, or read them in from a text file the user edited, and then send these to the Arduino in some non-volatile format?

I can see two possible approaches, and am fine with either, I just don't know how to implement either:

1) The editor edits the actual strings in the sketch, and then reloads the entire sketch to the the Arduino, so it's actually modifying the sketch. I imagine this would somehow use the command line loader, but I'm definitely in over my head sorting that out.

2) The editor communicates via serial with the Arduino, and the sketch on the Arduino receives just these strings from the editor,and stores them in EEPROM. To do this, the Arduino would have to sense whether or not it was connected via USB, I think, since otherwise I'm using the serial out to output MIDI.

In either case, I'm also trying to sort out the easiest way to install the appropriate drivers on the user's computer; do I need to have them install the whole IDE package, and then just use this editor to "program" the Arduino, or can I make a streamlined installer that would just install my editor and the necessary drivers. I want to make it as idiot proof as possible, since the end users will know even less about Arduino than I do!

I'd love something that is both Win and Mac friendly, but if I have to pick one, I'd go with Win, since that can run in Fusion or Boot Camp on Macs. Much as it pains me, being a Mac user myself :-1

Thanks in advance for any help, hand-holding, etc you can provide!

--Andy
Logged

0
Offline Offline
Edison Member
*
Karma: 8
Posts: 1411
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

If I understand correctly, you want to have an application running on PC that sends data to arduino on serial port.
Look at this thread
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1209217094/19#19
there is a piece of vb script that does just that.
On the arduino (receiving) side, you would have a piece of code that reads the COM port (with Serial.available(), Serial.read()).
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 29
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Nope, you misunderstand.

In normal operation, my program is not connected to a computer at all, it just spits out MIDI. But I want to provide the option (typically as a one time "setup") for my end user (who doesn't speak Arduino and I'd like to avoid having to make them putter around in the IDE) to change the values of a number of variables I declare in the beginning of the sketch permanently.

So I need to either give them a more automated way to reload the sketch onto the Arduino after they run a script that edits those values, or I need to have a way for the Arduino to tell that it's connected via USB, rather than MIDI (and this can even be as simple as holding a button down on boot, as long as the button can otherwise function as a normal input), and then to have the PC/Mac program send it those strings, and write them to EEPROM.

I fully understand the basics of how to get it to talk over serial, my issue is either booting the Arduino into an alternate "programming/editing" mode, in which case the program on the PC can send it those values, and the Arduino will write them to EEPROM, or to make a completely idiot-proof way to install the Arduino's drivers and have an automated "installer" to upload the sketch to the Arduino.

Does that explain what I need any more clearly?
Logged

0
Offline Offline
Edison Member
*
Karma: 8
Posts: 1411
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Well, I tried to simplify in my previous post. OK, let's recap (also simplified) what I understood that you want to do:
- your arduino, sometime, needs to read some values (could be many);
- these values should come by the way of serial communication (through USB, if you want), from PC;
- you want arduino to be able to enter a state where these values can be transfered from PC.

If this scenario sounds close to what you intent, these are my suggestions:
- have a button connected to arduino;
- when button is pushed, your sketch executes just the part with Serial.available + Serial.read;
- in the meantime, the connected PC sends the data;
- once the data is received by arduino, it can be written to eeprom.


Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 29
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

That's getting me closer. Question, and it may be a stupid newbie question, can I put code outside of the main loop, either in setup or elsewhere, so that it'll only go into the routine that does the serial read, eeprom, etc if that button is held down while the Arduino is first powered up?

I basically want to be able to put it into "editing" mode only when connected to the computer, be it by holding that button or sensing that it's connected to USB, but I don't want to have to add an additional button beyond the ones needed for normal operation, and I don't want the additional overhead of having to run that routine, or the check for the button to run that routine, every time it loops.

TIA,
Andy
Logged

0
Offline Offline
Edison Member
*
Karma: 8
Posts: 1411
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

So, you want to be able to read on serial port whenever the computer is connected. That is, whenever there is data on the serial port. This is nothing more than testing for available data at every loop, something like this:

void loop()
{
    // do your stuff here;
       ...

    // check for available data on serial port;
    if (Serial.available())
    {
        byte incomingByte = Serial.read();
        eeprom.write(addr, incomingByte);
    }
}

Tell me if I over-simplify.

Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 29
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Nope, not oversimplifying, just overlooking the part where I'm trying to NOT include this in the main loop, and to essentially make it an ancillary function that's only called if initiated immediately upon powering the Arduino.

I need to do this for two reasons:

1)Primarily, because the normal function of this project is to send and receive MIDI, and so it's already listening to the serial port normally, and needs to be able to discriminate these programming messages from MIDI

2)Overhead. I'd like to avoid even the simple overhead of having to check the serial port every time it loops were #1 not the case, but that being the case, if it were to listen to the code to distinguish MIDI from programming messages every time, it'd add a great deal of undesired overhead to the loop, potentially slowing things down.

That all said, I think I really need to pursue the other approach, of wholesale reuploading the sketch, since I had forgotten that EEPROM needs to be explicitly addressed, and since I can't know in advance how long the strings the end user will want to store will be, I can't easily store them in EEPROM, right?

So, can anybody gently guide me towards how to, for lack of a better way to describe it, create a self-installing sketch? That is to say, a file/program/script I can give the end user, and after he inserts his desired strings into it via whatever method I end up using (editing a text file that becomes part of the sketch, or using a GUI editor to do  it more transparently), it will upload itself?

I know it should be possible with the command line loader, I just don't know enough to understand how exactly that works, nor how to script that so it requires the least effort from the end user, ie, he just runs an installer, runs the program, and clicks "send program" and it uploads the modified sketch to the Arduino, without him having to muck around in the IDE.

TIA,
Andy
Logged

0
Offline Offline
Edison Member
*
Karma: 8
Posts: 1411
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

If you want to just upload a hex (compiled sketch) from command line (without the Arduino IDE), you can use

avrdude -pm168 -carduino -Pcom5 -b19200 -Uflash:w:mySketch.hex:a

But during the upload (and a bit after) your arduino won't execute your sketch.

A more elegant solution, in line with what I said so far, is to use an interrupt (from Rx pin) to "replace" the button mentioned earlier.

Your MIDI goes through the same Rx/Tx pins? Are you using same Tx/Rx for both MIDI and sketch upload?

In terms of programming effort, writing to eeprom is not more complicated than calling a function (or assigning values to variables). The only requirement is a delay of 5ms after a byte is written.

« Last Edit: April 11, 2009, 09:28:21 pm by florinc » Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 29
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Your MIDI goes through the same Rx/Tx pins? Are you using same Tx/Rx for both MIDI and sketch upload?

Well, MIDI comes out the serial pins, which while different physical pins are the same serial output as what the USB is connected to, right? Or am I just totally misunderstanding?

If I can segregate these functions programmatically, it shouldn't be an issue functionally, because the "programming" operation will never have to take place simultaneously with the MIDI mode. It would be a distinct process, before it's put into use.

Quote
In terms of programming effort, writing to eeprom is not more complicated than calling a function (or assigning values to variables). The only requirement is a delay of 5ms after a byte is written.

But don't I need to specifically address it to a given physical location in EEPROM? As opposed to just telling the Arduino "store 'XYZ123ABC' as 'StringA'" and then just letting it do its own thing with where to store that? So if I were dealing with a fixed amount of data, I could do EEPROM, but since I don't know whether each of the 7 strings the user could program would be 3 bytes, or 8 bytes, or whatever, I don't have a reliable way to either address them when writing, or to read them back.

Thinking out loud, I can see theoretically how I could have the PC program include a specific start and end byte for each string, so that the Arduino could just read/write them into EEPROM sequentially, and keep reading till it hits the next end byte, etc, I just have noooo idea how to implement reading that back into variables on the Arduino side of life.
Logged

0
Offline Offline
Edison Member
*
Karma: 8
Posts: 1411
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I would have built the device to talk MIDI using SoftwareSerial/NewSoftwareSerial.
I would have left Tx/Rx for hardware serial communication, as sometimes you need that, e.g. when you want to talk to the computer.

For read/write to eeprom, see this article in the playground.
http://www.arduino.cc/playground/Code/I2CEEPROM

As you say, you need to control the physical address where you store the data. That would be a global variable storing the address. If you always start writing the eeprom at the beginning, this value is 0 when you start writing.
You can separate the strings through the use of a CR (13), for example. You know that one string ends when you encounter a CR.

This is some code I use in one of my sketches to read a string from eeprom:
Code:

//...
char msgLine[200] = {0};
char* msgLinePtr = &msgLine[0];

int msgLineSize;      // size of the current string; set after line is read from eprom;
int msgLineIndex  = 0;

//...

byte readByte(int i2cId, unsigned int eeaddress)
{
  byte rdata = 0xFF;
  Wire.beginTransmission(i2cId);
  Wire.send((int)(eeaddress >> 8));    // Address High Byte
  Wire.send((int)(eeaddress & 0xFF));  // Address Low Byte
  Wire.endTransmission();
  Wire.requestFrom(i2cId, 1);
  if (Wire.available()) rdata = Wire.receive();
  return rdata;
}


byte readNextByte()
{
  byte rdata = readByte(I2C_ID, crtReadAddress);
  crtReadAddress++;
  return rdata;
}


void fetchLineFromEprom()
{
  // read a whole line into the message buffer;    
  byte lastReadByte = readNextByte();

  // after reaching the end of eprom's content, start from the beginning;
  if (lastReadByte == 0xFF || lastReadByte == 0)
  {
    crtReadAddress = 0;
    lastReadByte   = readNextByte();
  }

  while (lastReadByte != 13 && lastReadByte != 0xFF && lastReadByte != 0)
  {
    *msgLinePtr++ = lastReadByte;
    lastReadByte  = readNextByte();
  }

  // insert a few blanks (pause between messages);
  *msgLinePtr++ = ' ';
  *msgLinePtr++ = ' ';
  *msgLinePtr++ = ' ';

  // mark the end of the string;
  *msgLinePtr++ = 0;

//  Serial.println(msgLine);
  msgLinePtr  = &msgLine[0];      // reset the string pointer;
  msgLineSize = strlen(msgLine);  // update the size of the current string;
}

Logged

Pages: [1]   Go Up
Jump to: