Accelerometer-actuated servo for science project

Edit: This is not for a school project/homework. I work at a University lab and we’re willing to pay to solve this problem. Not much, but a reasonable amount - we need this figured out in the next week or so!

Hello dear Arduino community!
Re-post from Project Guidance after suggestions to post here.
Willing to negotiate price for help, but I’m hoping this is an easy fix/easy job for anyone to help complete.

I’m working on a science project that requires a 3d-printed gear to turn when a sensor box looks up at the sky and then turns the gear back the way it came when it looks at or below the horizon (kept simple and vague for the purposes of the arduino-focused situation).

Board: Nano 33 BLE Sense
Servo: Hitec HS-318 (not continuous rotation)
Degree of movement: from 0 (start) to 65 degrees (when box is tilted up) and then back to 0 (when box is pointing at or below the horizon).
Level of experience: beginner/intermediate (limited arduino programming, lots of hardware experience)

The Nano 33 BLE Sense was chosen to substitute our cheap, sensorless Nanos that don’t work due to unfortunate software/firmware compatibility issues…
Anyways, our hope is that the accelerometer/gyro (LSM9DS1) will suffice.

I purposely placed the // for (pos = […] ) because it did not work and I was hoping I could get help figuring out a solution, especially because the servo.write( ) did not work either.

A tilt switch has been ruled out because the other team that used one found it unreliable for our application as the sensor box moves a lot and gave false readings - hence our choice to go with an accelerometer.

Github references:
Arduino_LSM9DS1
Arduino Servo

After many hours of trying to cobble together some code based on forums and blog posts, I produced the code below. At first I tried IF/ELSE IF statements, but that didn’t seem to work well, so I tried IF &&, then finally ended up with the Boolean “switch” since the IF statements did not work properly (servo would react to tilt-up, but then would immediately revert back to original position without the device being tilted below the stated threshold).

#include <Arduino_LSM9DS1.h>
#include <Servo.h>
Servo myservo;
int pos = 0;
bool diffuser = false;

void setup() {
Serial.begin(115200);
while (!Serial);
Serial.println("Started");

myservo.attach(PIN_A6);
myservo.write(0)

if (!IMU.begin()) {
Serial.println("Failed to initialize IMU!");
while (1);
}

Serial.print("Accelerometer sample rate = ");
Serial.print(IMU.accelerationSampleRate());
Serial.println(" Hz");
Serial.println();
Serial.println("Acceleration in G's");
Serial.println("XtYtZ");

}

void loop() {
float x, y, z, delta = 0.35;

if (IMU.accelerationAvailable()) {
IMU.readAcceleration(x, y, z);

Serial.print(x);
Serial.print('\t');
Serial.print(y);
Serial.print('\t');
Serial.println(z);

if ((x >= delta) && (diffuser == false)){
  //for (pos = 0; pos == 65; pos += 1) {
  myservo.write(65);
  diffuser = !diffuser;
  Serial.println(diffuser);  // for the sake of identifying whether or not the boolean value changes (no luck)
  delay(1000);}  // arbitrary value - up for suggestions

else if ((x < delta) && (diffuser == !diffuser)) {
  //for (pos = 65; pos == 0; pos -= 1) {
  myservo.write(0);
  diffuser = !diffuser;
  Serial.println(diffuser);
  delay(1000);}
else delay(1000);
}
  delay(3000);
}

Since I’m unfamiliar with servo actuation and the servo position for loop, I decided to try the more direct route with the servo.write function, but that didn’t work either.

Any and all help would be much appreciated :sweat_smile: I thought this would be straightforward and simple, but I’m having such a hard time getting accelerometer data to actuate a servo… I’m hoping there will be a quick fix and a beautiful “aha!” moment.

Thanks for your time and support!

  • bobthebobster

This is odd:

if ((x >= delta) && (diffuser = false)){

because you used = instead of ==, that's equivalent to:

if(false)

Which isn't very useful.

Thanks, in my most recent update to the code that change was made, but no luck - the code still malfunctions.

Ok, post your most recent code and a description of what it's doing please.

wildbill:
This is odd:

if ((x >= delta) && (diffuser = false)){

because you used = instead of ==, that's equivalent to:

if(false)

Which isn't very useful.

Are you sure? I though the second part:

(diffuser = false)

always evaluates as true, while changing the value of diffuser to false (i.e. 0 (zero)).
I'd say the equivalent if statement would be:

if ((x >= delta)){

but then you don't have the additional fun of having a variable unexpectedly change value...

wvmarle:
Are you sure?

Yes - try it :slight_smile:

I thought the second part:

(diffuser = false)

always evaluates as true

No, it doesn't. It evaluates as whatever was assigned. Tangentially, it's why you can do this:

a=b=c=d=66;

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.