4

I'm trying to get students to experiment with Arduino. However, due to a lack of boards, two teams of students will collaborate on each board. They will push their own code (independent from each other) and use half the pins.

The "hardware" part isn't really a concern: students will push their sketches on a server that uploads them on the board, or something like that.

What I'm worried about is the software part. How can I allow two sketches to run on the same board, and allow the user to upload sketches without resetting the board?


As of my understanding, using the flash memory isn't an option, because the board must be reset before it can be written.

My first idea was to compile the students' C code into custom-made "assembly", and then push the assembly code to the board, which stores it into RAM and interprets it. However, my biggest problem would be implementing functions, I don't really have a clue of how I could do that. While common C functions could just be encoded in a fashion like FUNC printf STRING %s VAR a for printf("%s", a), I don't know how to encode user-defined functions. Besides, I don't even think the RAM is sufficient for running the client, storing two small programs, and running them.

Then, I thought about running the C code on the computer, but replacing digitalWrite with appropriate signals to the board. However, I'm worried about the performance of this, mostly when dealing with "high" speeds - say, using a custom-made library to print text on a LCD driver.

Giulio Muscarello
  • 143
  • 1
  • 1
  • 5

5 Answers5

4

In addition to the other answers, I have a few ideas:

1.) Instead of doing variable prefixes, have them wrap all of their code inside a namespace! Please note that you can't wrap "setup" or "loop" in that namespace. Example

setup() {
  if(conditionIsTrue) {
    aGroup::setup();
  } else {
    bGroup::setup();    
  }
}

loop() {
  if(conditionIsTrue) {
    aGroup::loop();
  } else {
    bGroup::loop();    
  }
}

namespace aGroup {
setup() {
  // Code
}

loop() {
  // Code
}
}

namespace bGroup {
setup() {
  // Code
}

loop() {
  // Code
}
}

2.)

Please note you'll have issues with a student tries to access an analog pin and doesn't prefix it with A. For example, if I wanted analog pin 5, I should do analogRead(A5);, not analogRead(5);. That could cause some major issues.

Anonymous Penguin
  • 6,365
  • 10
  • 34
  • 62
3

A little late, but I used a potentiometer as a switch to determine which "sketch" to run; in this case swapping LEDs on/off. I assume it can be applied to this instance, the students just have to share/divide pins and declare variables together at the top with comments. (I'm new at this, but I think a shift register (75HC595) could be used if you run out of pins). Thoughts?

EDIT: Potentiometers give a value of 0-1023. I split that up into 2, 3, and 4 separate sketches with no problems. You just have to change the IF/ELSEIFs to reflect how many sketches you want to run (512 for 2, 341 for 3, ~256 for 4, etc).

int sensorPin = 0;
int sensorValue = 0;
int ledPin1 = 4;
int ledPin2 = 8;

void setup() {

  pinMode(ledPin1, OUTPUT);
  pinMode(ledPin2, OUTPUT);
}

void loop() {

  sensorValue = analogRead(sensorPin);

  if (sensorValue < 512)
{
    digitalWrite(ledPin1,HIGH);
    digitalWrite(ledPin2,LOW);
}

  else
{
    digitalWrite(ledPin2,HIGH);
    digitalWrite(ledPin1,LOW);
}
}
Danny S.
  • 31
  • 1
2

How can I allow two sketches to run on the same board, and allow the user to upload sketches without resetting the board?

This is "easily" dealt with as long as you can enforce certain minimum disciplines.

Students must only use assigned pins.

Identifiers (functions, variables ...) defined by a group must always be unique to that group. This can be as simple as eg always starting with a group specific symbol or eg one group NEVER using a z in names and the other ALWAYS using Z etc. Annoying but easy.

Loop() contains calls to two non-terminating functions eg Group1() and Group2() All code for Group1 is in Group1() and ....

One digital pin is assigned for Giulio's use.
When GiuliosPin is low the system executes Group1() - and never exits it until restarted.
When GiuliosPin is high the system executes Group2() - and never exits it until restarted.

I uses a system very close to the Group1() / Group2() selection for my own purposes to allow multiple sketches to be compiled at once - but I use a constant which is set as I compile to choose which to run. My concern is the ability to test multiple code fragments.


Added:

After reading Mac's similar answer I see I missed mentioning Setup().
Code from both users can be merged into the same Setup() as the identifiers are unique.
Or the Setup() function for each Group can be carried out inside their unique Groupx() function with a "run once" function at the start of their code. This is a matter of programming discipline and not in any way hard per se.

Russell McMahon
  • 2,421
  • 11
  • 14
2

There is no native multitasking on an Arduino. A few solutions have been suggested above, all of which depend on cooperative multitasking - each half has to play fair.

An alternative may be this:

Buy some AtTiny chips - e.g. AtTiny 24a; they are about $2-3 each. Buy some VeroBoard. Solder the AtTiny on to the board, so each verboard strip has 2 pins on it (not the other way, where each veroboard strip has half of the pins on it). Solder on some pins, cut the track between the pairs of pins, and cut the board to size. You should be able to get a working board, with 12 usable pins per board, and you'll be paying less than $5 per board in your local currency. Buy a USBISP, and hook up the pins, whenever you need to program them - I suggest using the FreeTronics programmer, like this one here: http://www.jaycar.com.au/productView.asp?ID=XC4237 - you can solder 2 pins for the "slow clock" option - you'll need this. Optionally, you could make an adapter board which plugs into all of the relevant pins in one go, to program it. You should only need one of these. To figure out which wires to connect where, compare the top diagram on http://www.dz863.com/datasheet-8310956563-ATTINY24A-SSU_8-bit-Microcontroller-With-2k-4k-Bytes-In-system-Programmable-Flash/ with https://www.olimex.com/Products/AVR/Programmers/AVR-ICSP/resources/AVR-ICSP.gif

You can power them with AA batteries or an external power supply - you could easily make one power supply that runs many boards. Check out the spec sheet for the voltage required - it varies, depending on the clock speed (default clock speed as described is 1 MHz, google "avr fuses" for how to set them to e.g. 8 MHz at no extra cost).

Edgar Bonet
  • 45,094
  • 4
  • 42
  • 81
AMADANON Inc.
  • 2,383
  • 10
  • 9
0

There is a solution. It requires some programming discipline from your students, but it is feasible.

1) Make sure each group uses different variable and function naming conventions (one starts all variable and functions with a_ and the other group with b_). These functions will be written in separate include files.

2) In the setup() and in the loop() functions, you will call either a_setup() or b_setup(), and either a_loop() or b_loop(). Each of the group setup and loop functions will call their functions and use their variables as the groups want to, but they are not allowed to call variables/functions from the other group. Other resources can also be allocated by you in advance for each team.

3) During the setup() function, start by reading a specific input that you will either connect to GND or to 5V. Use the result of this reading to execute either one version of the software, or the other.

This is not elegant, but it gets two program into each Arduino.

MAC
  • 254
  • 1
  • 4