Arduino development
« Thursday, April 18, 2013 »

arduino

Today I destroyed one of my most complicated sketch… I opened one of my sketch and modified it to emulate one of our teacher's microcontroller. When I decided to save the sketch as a different project, I realised that I already saved and overwrited my old sketch. I then initialized a git repository and rewrote the whole thing. I haven't had time to test my code but I guess that it should work. It's not very optimal and there is probably many ways to make the code better.

The main sketch is quite simple:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include "CommandRegistry.h"

void switchLamp (String commandLine) {
  Serial.println("Lamp switched");
}

void getTime (String commandLine) {
  Serial.println("GetTime");
}

void setTime (String commandLine) {
  Serial.println("Set time");
}

CommandRegistry registry(10);

void setup(){
  Serial.begin(9600);

  registry.registerCommand("SET-TIME", setTime);
  registry.registerCommand("GET-TIME", setTime);
  registry.registerCommand("LAMP", switchLamp);
}

void loop(){

}

void serialEvent() {
  while (Serial.available()) {
    registry.serialEvent();
  }
}

And “CommandRegistry.h”

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#include <Arduino.h>

typedef void (*Command)(String);
typedef Command* Commands;

class CommandRegistry {
    String* names;
    Commands commands;

    String inputString;

    int count;
    int max_count;

    public:

    CommandRegistry(int size) {
        this->max_count = size;
        this->inputString.reserve(200);
        this->names = new String[size];
        this->commands = new Command[size];

        this->count = 0;
    } 

    void registerCommand(String name, Command callback) {
       this->names[this->count] = name;
       this->commands[this->count] = callback;
       this->count++;
    }

    void executeCommand(String name) {
      for (int i=0; i<this->max_count; i++) {
        if (names[i] && names[i] == name) {
            commands[i](this->inputString);
        }
      }
    }

    void handleCommand() {
       int index = inputString.indexOf('\r');
       String command;

       if (index >= 0) {
         command = inputString.substring(0, index);
         this->executeCommand(command);
       }
    }

    void serialEvent () {
      // get the new byte:
      char inChar = (char)Serial.read(); 
      // add it to the inputString:
      this->inputString += inChar;
      // if the incoming character is a newline, set a flag
      // so the main loop can do something about it:
      if (inChar == '\n') {
        this->handleCommand();

        this->inputString = "";
      } 
    }
};

I tried to keep the code as simple as possible. But I'm probably going to change the code to handle states. The CommandRegistry is a global object that handle serials events and execute commands. Each commands are expected to be of this format: “Name”. It's not yet possible to parse params but I could possibly do that. I plan to add a list command that will list all available commands and add a device-info that will return some information about the device.

Since my device is using the SPP profile, there is no real way to know which device connected and what it can do. The command registry is a good thing to implement if you expect to have multiple commands. On the other side, being able to create a state machine would be a good idea.

For my bluetooth device, I could create already three states: “Waiting”, “Pairing” and “Commanding”. The “Waiting” state is active whenever no client is connected to the device. It will fall in that state and wait to get paired to an other device. The “Pairing” state is issued whenever a device is connection to one other and we are sending whatever information the other device might need. The last state is issued last and may send back to the Waiting state. It should be able to send informations requested during pairing and it might create new states. This state could also be seen as the configuration state. Once in that state, the master device can send informations and the bluetooth device will execute whatever it can do.

When in Command state, it could be possible to fall into a data transfer state which would behave differently from the command state. Serial input would be redirected to something else instead of the commandRegistry. At this point, the SerialEvents are all going to the registry and this shouldn't behave that way.

comments powered by Disqus

Copyright © 2015 Loïc Faure-Lacroix