I can't help you with the JSON part of it, other than to say that it's best handled on the Linux side of things, and I'm sure someone versed in that aspect will be along to give you some hints.
Then there's the matter of sending/reading the servo positions. This will require some communications between the sketch and Linux sides of the Yun.
There are some pros and cons to the Bridge library, but I think this application is a reasonable use of the Bridge.put() and Bridge.get() mechanism. The Linux side reads and parses the JSON, extracts out the 5 servo positions, and "puts" those values to the shared Bridge storage, using a unique key for each motor ("m1", "m2", etc?)
The sketch is then very simple. In the loop() function, it steps through each servo: for each one, it calls Bridge.get() to read the servo position from the bridge, and write it to the servo output. That's all it needs to do.
The last known position of the servo is always accessible from the Bridge shared data store. The Linux side code can read that value and format up the data for the web page. One advantage of the Bridge is that it is easy to debug using a standard web browser:
-
http://arduino.local/data/put/m1/123 will store the value 123 under the key "m1"
-
http://arduino.local/data/get/m1 will return the value of the "m1" key
-
http://arduino.local/data/get will return the value of all keys stored in the Bridge
In Python, to use the bridge, you must have this at the beginning of your script:
sys.path.insert(0, '/usr/lib/python2.7/bridge/')
from bridgeclient import BridgeClient as bridgeclient
bc = bridgeclient()
After that, you can put a value to the shared store using:
bc.put('m1', '123')
And you can read a value using:
value = bc.get('m1')
Note that the bridge only works with strings, you will need to do the conversions back and forth from string to integer.
Some skeleton code for the sketch: (lots of details left out)
void setup()
{
Bridge.begin();
}
void loop()
{
processServo("m1", Servo1);
processServo("m2", Servo2);
processServo("m3", Servo3);
processServo("m4", Servo4);
processServo("m5", Servo5);
delay(50); // Give a little delay so the Bridge isn't swamped with communications.
// Or do other processing at this time if you have more to do.
}
void processServo(string key, Servo servo)
{
string value = Bridge.get(key); // Read the position
int position = value.toInt(); // Convert to integer
servo.write(position); // Output the servo position
}
The sketch doesn't write the current servo position back out, since the servo is open loop and we don't really know it's position. We just assume it's where we told it to go. If you do have an encoder or other feedback method, then you could read the value and put the value to another set of Bridge variables.
There are lots of optimizations that can be done. One is to keep track of the last known position of the servos in the sketch, and only write to the Servo output if the value has actually changed.
Another optimization is to have a single "new" key. When the Linux updates any of the motor positions, it sets the "new" key to "T". The sketch only reads the "new" key, and if it isn't "T" it does nothing else. If the "new" key is "T", it puts a value of "F" to the "new" key, and then processes the five servo positions. This method lightens the load on the bridge a bit, only polling one value most of the time rather than five.
There are quite still some details to work out, but that's the way I would approach it. Of course, there are lots of other ways. My thought is to do as much of the processing as possible in on the Linux side, and use the sketch to only do the actual hardware I/O operations. Some people don't like the Bridge, but this project is an ideal application for it: you need to store a limited set of data, and you are only interested int he current values. Why create a more complicated method when this one fits so well?