Display integration with servos

Hi there,

I am very new to arduino coding and have been working on a code that displays a sound graph that reads the input from a microphone while 2 servos move according to my input. I have managed to get a bit map to display, some text and then the servos move but for some reason the graph stays frozen. If I remove the servos from loop the graph gets displayed perfectly.

any advice on how to get the graph to function properly while the servos move.

here is my code

#include <U8glib.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SH110X.h>
#include <Servo.h>

// Set up the OLED display
#define OLED_MOSI     10
#define OLED_CLK      8
#define OLED_DC       7
#define OLED_CS       5
#define OLED_RST      9

Adafruit_SH1106G display = Adafruit_SH1106G(128, 64, OLED_MOSI, OLED_CLK, OLED_DC, OLED_RST, OLED_CS);


Servo servo1;
Servo servo2;

// Set up the sound sensor
const int sampleWindow = 50;  // Sample window width in mS (50 mS = 20Hz)
unsigned int sample;

// Graph variables
// Graph variables
const int graphWidth = 128;  // Width of the graph area
const int graphHeight = 60;  // Height of the graph area
const int graphX = 0;        // X-coordinate of the top-left corner of the graph area
const int graphY = 60;       // Y-coordinate of the bottom-left corner of the graph area
const int graphResolution = 2; // Resolution of the graph (increase for a smoother line)
int graphData[graphWidth / graphResolution]; // Array to store graph data
int graphIndex = 0;          // Index of the current graph data point



int openAngle1 = 60;       // Open position angle for servo1 (0 degrees)
int closeAngle1 = 150;    // Close position angle for servo1 (90 degrees)
int openAngle2 = 110;     // Open position angle for servo2 (30 degrees)
int closeAngle2 = 30;     // Close position angle for servo2 (100 degrees)
int stepDelay1 = 40;       // Delay between steps for the first set of movements (milliseconds)
int stepDelay2 = 5;      // Delay between steps for the second set of movements (milliseconds)
int stepDelay3 = 5;       // Delay between steps for the third set of movements (milliseconds)
int holdDuration1 = 10000; // Hold duration after stepdelay 1 close movement (milliseconds)
int holdDuration2 = 2000; // Hold duration after stepdelay 3 close movement (milliseconds)
int numMovements1 = 1;    // Number of movements for the first set of movements
int numMovements2 = 3;    // Number of movements for the second set of movements
int numMovements3 = 4;    // Number of movements for the third set of movements
int totalMovements = numMovements1 + numMovements2 + numMovements3;  // Total number of movements to perform

// Set up the bitmap image
const unsigned char PROGMEM bitmap[] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xbf, 0x0f, 0x80, 0x1c, 0x70, 0x3f, 0xdf, 0xc0, 0x3b, 0xfe, 0xe0, 0x70, 0xfa, 0x01, 0xff, 
0xff, 0x3f, 0x0f, 0x00, 0x0c, 0x60, 0x1f, 0xcf, 0xc0, 0x19, 0xfe, 0xc0, 0x30, 0xf2, 0x00, 0xff, 
0xff, 0x1f, 0x0f, 0x00, 0x0c, 0x60, 0x0f, 0x8f, 0xc0, 0x19, 0xfc, 0xc0, 0x10, 0xf2, 0x00, 0x7f, 
0xfe, 0x1f, 0x0f, 0x03, 0x8c, 0x47, 0x0f, 0x87, 0xc7, 0x18, 0xfc, 0x87, 0x10, 0xf2, 0x38, 0x7f, 
0xfe, 0x0f, 0x0f, 0x03, 0x84, 0x47, 0x8f, 0x07, 0xc7, 0x18, 0xf8, 0x87, 0x10, 0xf2, 0x38, 0x7f, 
0xfc, 0x0f, 0x0f, 0x03, 0x84, 0x47, 0x8f, 0x03, 0xc4, 0x18, 0x70, 0x87, 0x10, 0xf2, 0x00, 0xff, 
0xfd, 0x07, 0x0f, 0x03, 0x84, 0x47, 0x8e, 0x43, 0xc4, 0x18, 0x70, 0x87, 0x10, 0xf2, 0x00, 0xff, 
0xf9, 0x87, 0x0f, 0x03, 0x84, 0x47, 0x8e, 0xc1, 0xc4, 0x38, 0x20, 0x87, 0x10, 0xf2, 0x21, 0xff, 
0xfb, 0x83, 0x0f, 0x03, 0x84, 0x47, 0x8e, 0xe1, 0xc6, 0x38, 0x00, 0x87, 0x10, 0xf2, 0x31, 0xff, 
0xfb, 0xc3, 0x0f, 0x03, 0x84, 0x47, 0x0d, 0xe0, 0xc6, 0x1a, 0x08, 0x87, 0x10, 0xf2, 0x30, 0xff, 
0xf7, 0xc1, 0x0f, 0x03, 0x0c, 0x43, 0x0d, 0xf0, 0xc7, 0x1b, 0x08, 0xc7, 0x10, 0x72, 0x38, 0xff, 
0xf0, 0x41, 0x80, 0x40, 0x0c, 0x60, 0x18, 0x10, 0x47, 0x0b, 0x18, 0xc0, 0x18, 0x06, 0x38, 0x7f, 
0xe0, 0x61, 0x80, 0xc0, 0x1c, 0x70, 0x18, 0x18, 0x47, 0x03, 0x98, 0xe0, 0x38, 0x0e, 0x3c, 0x7f, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x01, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x06, 0x40, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x84, 0x00, 0x00, 0x63, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc7, 0xe0, 0x07, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xf8, 0x3f, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x5c, 0x34, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xdc, 0x32, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x9c, 0x72, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x8e, 0xf2, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x0f, 0xf0, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x1f, 0xf0, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x1f, 0xf0, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x1f, 0xf0, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f, 0xf0, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x1f, 0xf0, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x1f, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
};

void setup() {


  servo1.attach(3);      // Attach servo to pin 3
  servo2.attach(6);      // Attach servo to pin 6
  servo1.write(openAngle1);  // Set initial position of servo1
  servo2.write(openAngle2);  // Set initial position of servo2
  
  
  Serial.begin(9600);
  display.begin(0, true); // start OLED display
  display.clearDisplay();
  display.drawBitmap(0, 0, bitmap, 128, 64, 1);
  display.display(); // show bitmap for 10 seconds
  delay(5000); // delay for 10 seconds
  display.clearDisplay(); // clear the display


  display.setTextSize(2);
  display.setTextColor(SH110X_WHITE);
  display.setCursor(0,0);
  display.println("TEST: 01");
  display.display();
  delay(5000);
  
  
  display.setTextSize(1);
  display.setTextColor(SH110X_WHITE);
  
  // Initialize the sound sensor
  pinMode(A0, INPUT);
  sample = 0;


}

void loop() {


  unsigned long startMillis = millis();  // Start of sample window
  unsigned int peakToPeak = 0;           // Peak-to-peak level

  unsigned int signalMax = 0;
  unsigned int signalMin = 1024;

  // Collect data for the sample window
  while (millis() - startMillis < sampleWindow) {
    sample = analogRead(A0);
    if (sample < 1024) {  // Remove DC offset
      if (sample > signalMax) {
        signalMax = sample;  // Find maximum value
      } else if (sample < signalMin) {
        signalMin = sample;  // Find minimum value
      }
    }
  }
  peakToPeak = signalMax - signalMin;  // Peak-to-peak level

  // Update the graph data
  graphData[graphIndex] = map(peakToPeak, 0, 1023, graphY, graphY - graphHeight);

  // Display the sound level and graph on the OLED screen
  display.clearDisplay();
  display.setCursor(0, 0);
  display.print("Sound Level: ");
  display.print(peakToPeak);
  
  // Draw the graph
  for (int i = 0; i < graphWidth / graphResolution - 1; i++) {
    display.drawLine(graphX + i * graphResolution, graphData[(graphIndex + i + 1) % (graphWidth / graphResolution)], 
                     graphX + (i + 1) * graphResolution, graphData[(graphIndex + i + 2) % (graphWidth / graphResolution)], SH110X_WHITE);
  }
  
  display.display();
  
  // Update the graph index
  graphIndex = (graphIndex + 1) % (graphWidth / graphResolution);
  
// Delay for stability
  delay(20);
   for (int i = 0; i < totalMovements; i++) {
    // Move servos from open to close position
    for (int angle = openAngle1; angle <= closeAngle1; angle++) {
      servo1.write(angle);
      servo2.write(map(angle, openAngle1, closeAngle1, openAngle2, closeAngle2));

      if (i < numMovements1) {
        delay(stepDelay1);
      } else if (i < (numMovements1 + numMovements2)) {
        delay(stepDelay2);
      } else if (i < totalMovements) {
        delay(stepDelay3);
      }
    }

    // Hold position after stepdelay 1 close movement
    if (i == (numMovements1 - 1)) {
      delay(holdDuration1);
    }

    // Move servos from close to open position
    for (int angle = closeAngle1; angle >= openAngle1; angle--) {
      servo1.write(angle);
      servo2.write(map(angle, openAngle1, closeAngle1, openAngle2, closeAngle2));

      if (i < numMovements1) {
        delay(stepDelay1);
      } else if (i < (numMovements1 + numMovements2)) {
        delay(stepDelay2);
      } else if (i < totalMovements) {
        delay(stepDelay3);
      }
    }

    // Hold position after stepdelay 3 close movement
    if (i == (numMovements1 + numMovements2 - 1)) {
      delay(holdDuration2);
    }
  }

  // Stop the servos
  servo1.detach();
  servo2.detach();

  // Stop the loop
  while (true) {
    // Do nothing
  }
}```

That is not necessary. In fact, it just… detaches the servos. I don't see that you re-attach them.

So not only do they stop, they go dumb.

Servos don't need to be stopped.

A regular servo will stop moving if you stop calling it, or continue to call it with the same angle value.

Continuous rotation servos stop by (typically) setting the desired "angle" to 90. I say "angle" because in this case numbers greater than 90 mean rotate CW, the further away from 90 the faster, and below 90 means CCW, again the further away from 90 the faster.

Attach the servos once, control them by the angle number.

Usually there is no need to detach a servo. They can remain attached until you pull the plug on the hole thing.

I did not otherwise look at you code. Outta gas here TBH.

Except… did you post the code you are talking about that kinda sorta works?

This makes me ask:

  // Stop the loop
  while (true) {
    // Do nothing
  }

That pretty much is game over for anything happening anymore at all.

a7

why?

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