Skills Dev V: Working with Networking

Made by Xuan Peng, Yuhan Wu and Junke Zhao

A pair of connected devices passing trigger information to each other's servo.

Created: December 16th, 2023

0

Outcome

The team explored the paired device exercise with a servo to signal a classic vibration of phones. 

The argon and phone attached to servos are places in the order (A, B, C from the left to right), the calling sequence is C to B, B to A, A to C...

The serial monitor in the foreground belongs to argon B in the middle. It shows its work as both subscription and publish.

0
Phone Callin' Skill Dev 5
DIOT-Max - https://youtu.be/1q1eC4e0_Kc
0
Servo myServo;

int potPin = A5;

int lastPos = -1;
int pairPos = -1;
bool allowDialInput = true;  
// Flag to control dial input

unsigned long lastSubscriptionTime = 0;
const unsigned long dialInputTimeout = 2000;  
// Time out to disable the dial at a period of time 

void setup() {
  Serial.begin(9600);
  myServo.attach(A3);
  Particle.variable("servoPos", myServo.read());
  Particle.subscribe("spinServo", handleSpinServo);
}

void loop() {
  int potReading = analogRead(potPin);
  int mappedPos = map(potReading, 0, 4095, 20, 160);
  if (abs(mappedPos - lastPos) > 20 && allowDialInput) {
    Particle.publish("doPairedPublish", String(mappedPos));
    // Publish the updated servo position to next device
    // and print in serial monitor
    Serial.print("Publish servo position: ");
    Serial.println(mappedPos);

    // Update the last known position
    lastPos = mappedPos;

    // Add a delay to avoid rapid updates
    delay(500);
  }

  // Check if the timeout has passed, re-enable dial input
  if (!allowDialInput && millis() - lastSubscriptionTime >= dialInputTimeout) {
    allowDialInput = true;
    Serial.println("Dial input re-enabled");
  }
}

void handleSpinServo(const char *event, const char *data) {
    int newPos = atoi(data);
    allowDialInput = false;
    myServo.write(newPos);
    // Disable dial input when handling external subscription
    // Set the servo position based on the subscribed value
    pairPos = newPos;
    // Record the paired position
    Serial.print("Set servo position via subscribe to: ");
    Serial.println(newPos);
    // Print the updated servo position to the serial monitor

    // Record the time of the subscription
    lastSubscriptionTime = millis();
}
Click to Expand
0

Process

Started with prototyping the paired devices that can rotate a same degree with the output of a servo, we initially made the two phones vibrate together when any button was pushed, but we wanted to make this action more interactive, so we chose knobs that allow the user to control the servo more to their heart's content to convey more information.    

And then we add a dial to provide a more interactive reading for the project. During testing with the project we found that the reading of two dials on separate argon could trigger the servo to move back and forth, which is also a pretty intriguing pattern. If the mapped value of the dial match within a tolerance angle of 20, the two servo would be stable and static, but if the gap is bigger than that, they would send local reading value of the dial to each other and keep swapping that reading from the dial.

We thought that to control in terms of a loop of 3, it might be more effective if we only publish the pot reading to the subscription and avoid the duplication of a local dial reading as well as the reading from other devices.

0

Below is code and video of process work and demo. It shows the sync servo function and the conflict of different reading of two dials.

0
Servo myServo;

int potPin = A5;

int lastPos = -1;
int pairPos = -1;
bool allowDialInput = true;  // Flag to control dial input

unsigned long lastSubscriptionTime = 0;
const unsigned long dialInputTimeout = 2000;  

void setup() {
  Serial.begin(9600);
  myServo.attach(A3);
  Particle.variable("servoPos", myServo.read());
  Particle.subscribe("spinServo", handleSpinServo);
}

void loop() {
  int potReading = analogRead(potPin);
  int mappedPos = map(potReading, 0, 4095, 20, 160);

  // Only update the servo position if the potentiometer reading has changed significantly
  if (abs(mappedPos - myServo.read()) > 20 && allowDialInput) {
   
    myServo.write(mappedPos);
    Serial.print("Set servo position to: ");
    Serial.println(mappedPos);

    Particle.publish("doPairedPublish", String(mappedPos));

    Serial.print("Published new position: ");
    Serial.println(mappedPos);

    lastPos = mappedPos;
    delay(500);
  }

  // Check if the timeout has passed, re-enable dial input if necessary
  if (!allowDialInput && millis() - lastSubscriptionTime >= dialInputTimeout) {
    allowDialInput = true;
    Serial.println("Dial input re-enabled");
  }
}

void handleSpinServo(const char *event, const char *data) {
  // Convert the data to an integer representing the new servo position
  int newPos = atoi(data);

  // Disable dial input when handling external subscription
  allowDialInput = false;
  myServo.write(newPos);

  // Record the paired position
  pairPos = newPos;
  Serial.print("Set servo position via subscribe to: ");
  Serial.println(newPos);

  lastSubscriptionTime = millis();
}
Click to Expand
0
Skills Dev 5
Xuan - DIoT - https://youtu.be/LSUKKiDv4pE
0

Reflection

As demonstrated in the video above, the sync function works in an interesting pattern by could cause the conflict in dial reading value. The potential solution besides eliminate the local control feature maybe more compelling if we use a slider or push button to control wether or not the data is going to be published or submitted to be used for the local servo. If possible, the exchange could be oriented by a single slider.

We really like the expression form of two old phones, which kind of brought us back to the time that phone was just used to communicate with each other, instead of taking time away from the social life we're supposed to have. For next steps we might consider adding one more sensor to convey more information using light or sound.

x
Share this Project

Courses

48-675 Designing for the Internet of Things

· 11 members

A hands-on introductory course exploring the Internet of Things and connected product experiences.


About

A pair of connected devices passing trigger information to each other's servo.