Better long running custom Firmata functions

If you managed to get to this part, you have seen how simple wired communication protocol between two Arduino’s is transformed into communication over Bluetooth using the Firmata protocol. Great!

Now we take a look, again, at a demo given at the Ignite 2015 in Australia. In this demo, an ultrasonic distance reader is used to generate a custom stream of measurement.

Although it’s a demo and it serves a purpose, the solution shown has an architectural flaw. If we look deeper into the Arduino code, we will find a ‘while (true) {}’. It is put inside a switch inside the ‘custom function handler’ sysexCallback().

Yes, this generates a constant stream of measurement but it also locks up the Firmata on the Arduino. No other call will de handle anymore because the endless loop is just blocking further communication.

This is part 6 of a series of blogs about device communication between Arduino, RaspberryPi etc:

  • Part 1: Using I2C to connect two Arduino Nano’s
  • Part 2: Using I2C between Raspberry Pi Master and Arduino Slave
  • Part 3: Use Bluetooth between Win 10 UWP and Arduino
  • Part 4: Add virtual Arduino ports to your UWP app
  • Part 5: Custom Firmata function called by Windows 10 IoT Core
  • Part 6: Better long running custom Firmata functions
  • Part 7: Custom servo usage in Firmata
  • Part 8: Using NRF24L01+ modules between arduino’s
  • Part 9: Cheap Arduino mesh using RF24 radio modules

But a solution is pretty simple. All we need is a Start/Stop function which sets a boolean member to true or false within the Firmata sketch. And in the regular message loop, this function is called is the value is true.

So wat we need first is a new button:

<Button Name="btnSwitchMeasurement"
        Click="btnSwitchMeasurement_Click"
        FontSize="20"
        Content="Switch" />

And behind that button we have a switch function call:

private bool _switched = false;
 
private void btnSwitchMeasurement_Click(object sender, 
                                       RoutedEventArgs e)
{
    _switched = !_switched;
 
    byte value = Convert.ToByte(_switched);
 
    byte ULTRASONIC_DISTANCE_QUERY_SWITCH = 0x46;
    _firmata.sendSysex(ULTRASONIC_DISTANCE_QUERY_SWITCH, 
                       new byte[] { value }.AsBuffer());
    _firmata.flush();
}

We remember the last value in _switched to we can send an On and Off command.

Now we move over to the Arduino sketch. We define a new functionidentifier and we set a boolean member which indicates when to send a ultrasonic measurement:


#define ULTRASONIC_DISTANCE_QUERY_SWITCH 0X46

bool sendUltrasonic = false;

Now we implement the custom function inside de switch in sysexCallback():


case ULTRASONIC_DISTANCE_QUERY_SWITCH:
  if (argc > 0)
  {
    sendUltrasonic = (argv[0] == 1);
  }
  else
  {
    sendUltrasonic = false;
  }
  break;

So we set the member sendUltrasonic to true or false according to the value received.

Then we look at the overall loop. just a conditional call to the function which will do the real call:


void loop()
{

  ...

  if (sendUltrasonic)
  {
    measureDistance();
  }
}

So now, if sendUltrasonic is set to true, we can send the distance in a continuous stream. Just call measureDistance() for one measurement:

void measureDistance()
{
  long duration;
  long distance;
  String distanceAsString;
  pinMode(ultrasonicTriggerPin, OUTPUT);
  digitalWrite(ultrasonicTriggerPin, LOW);
  pinMode(ultrasonicEchoPin, INPUT);
  digitalWrite(ultrasonicTriggerPin, LOW);
  delayMicroseconds(2);
  digitalWrite(ultrasonicTriggerPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(ultrasonicTriggerPin, LOW);

  duration = pulseIn(ultrasonicEchoPin, HIGH);
  distance = duration / 52.2;

  distanceAsString = String(distance);

  Firmata.sendString(distanceAsString.c_str());
  delay(1000);
}

This function just contains the same logic as in the original demo but now without that blocking While loop.

So now try your app and see how you can start and stop the stream of measurements. And better, if you included the code of the previous parts, you can still manipulate port 13 (the LED) and do an echo.

Advertenties