Industrielle Fertigung
Industrielles Internet der Dinge | Industrielle Materialien | Gerätewartung und Reparatur | Industrielle Programmierung |
home  MfgRobots >> Industrielle Fertigung >  >> Manufacturing Technology >> Herstellungsprozess

Arduino Bluetooth-gesteuerter motorisierter Kamera-Slider

Komponenten und Verbrauchsmaterialien

Arduino UNO
× 1
PCBWay Custom PCB
https://www.pcbway.com/project/shareproject/Arduino_Motorized_Camera_Slider.html
× 1
V-Slot 20×40 Linearschiene
die gewünschte Länge.
× 1
Solid-V-Radsatz
× 4
Solid-V-Radsatz
× 4
Drop In Tee Nuts
× 4
Drop In Tee Nuts
× 4
Exzentrischer Abstandhalter
× 2
Exzentrischer Abstandhalter
× 2
9 mm Aluminium-Abstandshalter
× 2
9 mm Aluminium-Abstandshalter
× 2
3 mm Aluminium-Abstandshalter
× 2
M5-Schrauben mit niedrigem Profil, Länge 20 mm mit Muttern
× 4
M5-Schrauben mit niedrigem Profil, Länge 10 mm
× 4
M3 Innensechskantschrauben Länge 16mm mit Muttern
× 8
Selbstausrichtendes 8-mm-Stehflanschlager
× 2
GT2 Bohrung 8mm 20 Zähne Aluminium Riemenscheibe
× 1
8-mm-Linearschienenwelle
60 mm Länge
× 1
GT2 Bohrung 5mm 20 Zähne Aluminium Riemenscheibe
× 1
GT2-6mm offener Zahnriemen
die Länge des Riemens, hängt von der Länge der Aluminiumprofilschiene ab
× 1
bipolarer Nema17-Schrittmotor
× 1
A4988 Schrittmotortreiber
× 1
12V 3A Akku
× 1
HC-05 Bluetooth-Modul
× 1

Notwendige Werkzeuge und Maschinen

3D-Drucker (generisch)

Apps und Onlinedienste

Autodesk Fusion 360
Aurodesk-Eagle
Arduino-IDE

Über dieses Projekt

Projektübersicht

Für jemanden, der es liebt, zufällige Hobbyvideos zu drehen, ist es irgendwie teuer, einen motorisierten Kameraschieber zu kaufen. Also habe ich mein eigenes gebaut. In diesem Tutorial werden wir jeden Schritt durchgehen, um Ihren eigenen Bluetooth-gesteuerten motorisierten Kamera-Slider zu bauen.

Heute bauen wir einen motorisierten Kamera-Slider, den wir drahtlos über Bluetooth von einer maßgeschneiderten Android-App steuern können. Ich habe das Tool "MIT App Erfinder" verwendet, um die App zu erstellen, die uns die Möglichkeit gibt, viele Dinge wie die Geschwindigkeit der Schieberbewegung, die Fahrstrecke, die Beschleunigungs- / Verzögerungsrate und vieles mehr zu steuern. Die mobile App ist sehr robust, innerhalb der App können Sie die Länge Ihres Kameraschiebereglers einstellen, den Sie verwenden. Das heißt, Sie können Ihren tatsächlichen Kamera-Slider mit einer beliebigen Länge von bis zu 10 Metern bauen, ohne sich um die App kümmern zu müssen.

Wir haben einen NEMA17-Schrittmotor als Aktuator verwendet, damit wir steuern können, wie viele Schritte wir den Kameraschieberegler zum Bewegen benötigen. Um einen Schrittmotor mit dem Arduino-Board zu steuern, benötigen wir einen Übersetzer, der Befehle vom Arduino-Board aufnimmt und in die Sprache übersetzt, die der Schrittmotor versteht. Hier kommt die A4988 Pololu Schrittmotortreiberrolle, die uns fünf verschiedene Mikroschrittauflösungen (bis zu 1/16 Schritt) bietet, um die maximale Bewegungsgenauigkeit und Bewegungsglätte zu erreichen.

Dieses Projekt wurde mit Blick auf die Machbarkeit in einem Fablab/Makerspace/Hackerspace entwickelt.

CAD und 3D-Modellierung

Wir haben Fusion360 verwendet, um den Kamera-Slider zu entwerfen. Wir haben uns für die Verwendung sehr bekannter, leicht zu findender mechanischer Komponenten entschieden, die Sie problemlos in fast jedem Online- oder Offline-Geschäft kaufen können, egal wo Sie leben.

Wir verwenden Openbuilds-Hardware, um die mechanische Struktur zu bauen, die V-Slot 2040-Linearschiene als Führung für die Kamera. Zwei Riemenscheiben, eine auf der Schrittmotorwelle. Und das andere auf einer 8-mm-Linearschienenwelle auf der gegenüberliegenden Seite des Schiebers mit einem offenen Zahnriemen dazwischen, um die Drehbewegung des Schrittmotors in eine Linearbewegung umzuwandeln.

Die 8-mm-Linearschienenwelle wird zwischen zwei selbstausrichtenden Stehlagerbocklagern installiert, die mit vier M5-Schrauben an der oberen und unteren Platte montiert sind.

Wir verwenden vier Delrin V-Slot-Vollräder, die in der V-Nut der V-Slot-Schiene nach unten fahren, um die Kamerabewegung extrem glatt zu machen. In der Mitte der Kameraplatte befindet sich ein Loch mit einem Durchmesser von 1/4 Zoll für eine Standard-Stativschraube, damit Sie Ihre Kamera einfach montieren können.

Schließlich ein Gehäuse für die Elektronik. Alle Teile des Kameraschiebers sind mit m3 * 16 mm Schrauben und Muttern zusammen befestigt.

Digitale Fertigung (3D-Druck)

Der gesamte Kamera-Slider-Körper ist 3D-gedruckt mit 0,2-Schichthöhe, 20% Füllung, mit Ausnahme des linken und rechten Beins des Kamera-Schiebereglers, wird mit 0,2-Layer-Höhe und 50% Füllung gedruckt.

Sie können die STL-Dateien herunterladen von Thingiverse.

Montage des V-Radsatzes

Der Montageprozess ist sehr einfach, Mann, komm schon! Im ersten Schritt müssen wir die vier Solid V-Wheels montieren. Das solide V-Rad-Kit wird mit einem Gummirad, zwei Lagern, zwei Passscheiben und einer Sicherungsmutter geliefert.

Setzen Sie das Lager von einer Seite des Gummirads ein und drehen Sie das Rad herum, legen Sie dann eine Präzisionsscheibe in das Gummirad ein und setzen Sie zuletzt das zweite Lager von der zweiten Stirnseite ein.

Mechanische Baugruppe des Kameraschiebers

Zuerst müssen wir die Kameraplatte und die vier soliden V-Wheels zusammenbauen. Verwenden Sie das 9-mm-Aluminium-Abstandsstück, die Präzisionsscheibe und die Kontermutter.

Wir werden den vorherigen Schritt mit den anderen drei Rädern wiederholen. in den beiden rechten Rädern verwenden wir den 9-mm-Distanzring. Und bei den anderen beiden linken Rädern werden wir den exzentrischen Spacer mit einem 3 mm Spacer anstelle des 9 mm Spacer verwenden.

Setzen Sie nun die Kamerahalterungsplatte in das V-Nut-Profil ein. Wenn Sie feststellen, dass die Platte locker ist und wackelt, können Sie die Exzentermutter festziehen, bis Sie eine feste Platte erhalten.

Lassen Sie uns zwei Drop-In-T-Muttern in jedes Ende des V-Slot-Profils einsetzen. Wir müssen das V-Slot-Profil mit dem rechten und linken Bein des Kameraschiebers verbinden.

Holen Sie sich die beiden Kameragleiterbeine und schieben Sie sie in das V-Slot-Profil.

Bringen Sie vier M5X10mm Schrauben mit und befestigen Sie die beiden Beine mit dem V-Slot-Profil.

Wir müssen den NEMA 17-Schrittmotor auf seiner Platte installieren. Dann werden wir den Motor mit vier M3X16mm Schrauben befestigen.

Setzen Sie am linken Bein zwei Muttern in die obere Mutternposition des linken Beins ein.

Bringen Sie die NEMA 17-Motorplatte mit und befestigen Sie sie oben am linken Bein. und mit zwei M3X16mm Schrauben werden wir die Platte am linken Bein befestigen.

Um die Drehbewegung des Schrittmotors in eine Linearbewegung umwandeln zu können, müssen wir eine GT2 Bore 5mm Riemenscheibe auf der Motorwelle installieren. und ziehen Sie die Stellschraube der Riemenscheibe mit dem Inbusschlüssel fest, um sie in Position zu halten.

Gehen wir zum rechten Bein des Kameraschiebers und setzen Sie vier M3-Muttern an der Stelle der Beinmuttern ein.

Legen Sie dann das rechte Bein mit den beiden Platten oben auf das rechte Bein des Kameraschiebers.

Befestigen Sie die beiden Platten mit vier M3X16mm-Schrauben am rechten Bein des Kameraschiebers, um sie in Position zu halten.

Bringen Sie eines der 8-mm-Flanschblocklager und installieren Sie es auf der oberen rechten Beinplatte. mit zwei M5X20mm Schrauben und zwei M5 Muttern.

Wir müssen den vorherigen Schritt mit dem zweiten 8-mm-Flanschlagerblock wiederholen, um ihn an der unteren Platte des rechten Beins des Kameraschiebers zu befestigen.

Führen Sie die 8mm Linearschienenwelle von der Unterseite in den 8mm Flanschlagerblock ein und schieben Sie sie nach oben. Setzen Sie dann die Riemenscheibe mit 8 mm Bohrung in die Linearschienenwelle ein und befestigen Sie sie durch Anziehen der Stellschraube der Riemenscheibe.

Checkpoint, Jetzt haben wir den gesamten Kamera-Schiebemechanismus zusammengebaut, bis auf eine Sache. der Zahnriemen. Lass es uns tun.

Drehen Sie den 6-mm-Zahnriemen auf der Riemenscheibe mit 5 mm Bohrung des NEMA17-Motors. Auch am rechten Bein 8mm Bohrung Riemenscheibe. Ziehen Sie zuletzt den Gürtel mit der Kameraplatte fest.

Es ist Zeit, die Steuerplatine zusammenzubauen. Setzen Sie das Arduino-Schild des Cairo Camera Slider auf die Oberseite des Arduino-Boards.

Setzen Sie die Arduino-Platine und den Cairo Camera Slider-Schild in das Gehäuse der Steuerplatine ein.

Setzen Sie zwei M3-Muttern in die linke Beinmutter ein.

Installieren Sie das Gehäuse der Steuerplatine mit M3X16mm Schrauben am linken Bein des Cairo Camera Slider.

Schließen Sie die Oberseite des Gehäusekastens mit zwei M3-Schrauben und Muttern, und das war's!

Stepper Motor Test Control

After assembling all the parts together, We need to test it to make sure that everything is installed in its place correctly. Now, we need to connect the stepper motor with the Arduino board through the A4988 stepper motor driver and write some code to run that thing.

A4988 stepper motor driver

To control any stepper motor using the Arduino board or any microcontroller, you will need a stepper motor driver which works as a translator, takes commands from the Arduino board and translate it to the language that the motor understands.

there are a lot of stepper motor drivers out there but we will use the A4988 driver . This driver allows us to control one bipolar motor at up to 2A output current per coil, it’s very simple to interface with the Arduino board you only need two digital pins to fully control your motor step and direction, allows you to control the maximum current output easily with an onboard potentiometer, and gives you a micro-step resolution down to 1/16 micro-step.

VMOT, GND: It’s the power connection pins for the stepper motor itself, it can be 8V-35V. In our case, we are connecting a 12V 3A power source on those pins with a 100uf decoupling capacitor to protect the A4998 board from any power spikes.

2B, 2A: the output pins for the stepper motor first coil which can deliver up to 2A.

1A, 1B: the output pins for the stepper motor second coil which can deliver up to 2A as well.

VDD, GND: Used for driving the internal logic circuitry, it can be 3V to 5.5V. It’s totally isolated from the VMOT pin.

EN: Stands for “Enable” it’s an active LOW(0V) input pin, which means when this pin pulled LOW(0V) the A4988 chip is enabled. And when pulled HIGH(5V) the A4988 chip is disabled. By default, this pin is pulled LOW(0V). So, the chip is always enabled unless you pull it HIGH(5V).

MS1, MS2, MS3: Through these pins, you can select your motor microstepping resolution(step size). The A4988 gives you five different microstep resolutions (full step, half step, quarter step, Eighth step, Sixteenth step) . By applying appropriate logic levels to these three pins we can set the motors to one of the five step resolutions.

By default, the MS1, MS2, MS3 pins have internal pull-down resistors. So leaving these three microstep selection pins disconnected results in full-step mode.

RST, SLP: The “Reset” pin is an active LOW(0V) input pin, which means when it pulled LOW(0V), all the step inputs are ignored it also resets the translator itself until you pull it HIGH(5V). The “Sleep” pin also an active LOW pin, pulling it LOW, puts the driver in the sleep mode minimizing the power consumption. By default, the “Sleep” pin is pulled HIGH(5V).

STP, DIR: The “Step” pin is responsible for controlling the number of steps that the motor is rotating, each pulse to the “Step” pin corresponds for one microstep in the direction selected by the “Direction” pin, the faster the pulses, the faster the motor will rotate. By applying logic value HIGH(5V) on the “Direction” pin it makes the motor rotate clockwise, by applying LOW(0V) it makes the motor rotate counterclockwise(it may differs from one to another according to your motor wiring with the driver).

NEMA17 Stepper Motor

Stepper motors are DC motors that can rotate in precise increments, they are used in many applications like 3D printers to align the printhead and CNC machines to control the movement of the cutting tool and this is because they are very accurate and precise.

Unlike DC motors, stepper motors are controlled by applying DC electrical pulses to their internal coils. Each pulse makes the shaft advance by one step or a fraction of step which is called “Microstepping”. So, you can control precisely how many steps or even fraction steps you want the motor shaft to move. Another great advantage of using stepper motors is that it can move very precisely and accurately at very slow speeds without even stalling.

The type of motor we are using in this project is the NEMA 17 Bipolar stepper motor . The bipolar stepper motor has two internal coils and it usually has four wires, two wires per coil. unlike the Bipolar stepper motor which has five wires. The “Step Angle” of the motor is 1.8° which indicates how much the shaft advances in each full step, the motor works on 9V but if you want to get the maximum power of it use a 12V power source.

So, by connecting the stepper motor with the A4988 stepper motor driver, we can control how many steps we need the motor to move and in what direction. Also, we can set the “microstep” mode is it full step, half step, quarter step, ….. Let’s take a look at the wiring diagram.

Wiring Diagram

As we stated before, we need to make a small check to make sure that everything we assembled before is right in its place and moving properly. Now, we will wire all the hardware together, the NEMA 17 stepper motor with the A4988 stepper motor driver to the brain, the Arduino board. And using a 12V 3A Lithium-Ion battery to feed the motors with the power it needs.

Arduino Code

AccelStepper Library Installation

The Installation is pretty simple, we need to open Arduino IDE. From the “Sketch” menu. Select Include Library –> Manage Libraries…

A new window should appear, search for “AccelStepper” and install the library made by “Mike McCauley”. Easy right!

After installing the AccelStepper library, you should see it in the examples menu.

I wanna make sure that the AccelStepper library is installed correctly and my stepper motor connection with the A4988 motor driver is right and my power management is fine. So, let’s write some lines of code to run our stepper motor forward and backward.

// Bounce stepper test program
// Make a single stepper bounce from one limit to another
// Copyright (C) 2020 makesomestuff.org

#include
#define stepPin 2
#define dirPin 3 // Define a stepper and the pins it will use

AccelStepper stepper(AccelStepper::DRIVER, stepPin, dirPin); //create an object. the pin "2" is the step pin, "3" is the direction pin.

void setup()
{
// Change these to suit your stepper if you want
stepper.setMaxSpeed(100);
stepper.setAcceleration(20);
stepper.moveTo(500);
}

void loop()
{
// If at the end of travel go to the other end
if (stepper.distanceToGo() ==0)
stepper.moveTo(-stepper.currentPosition());
stepper.run();
}

The code logic is pretty straightforward, we initialized an object from the AccelStepper library, we defined two constants (stepPin, dirPin) that two digital pins is used by the A4988 stepper motor driver to control the movement of the motor itself.

#include 

#define stepPin 2
#define dirPin 3 // Define a stepper and the pins it will use

AccelStepper stepper(AccelStepper::DRIVER, stepPin, dirPin); //create an object. the pin "2" is the step pin, "3" is the direction pin.

Inside the void setup function, we set the Max. speed of the stepper motor to 100 steps/sec. Also, we set the acceleration/deceleration rate to 20 steps/sec. lastly, we used the moveTo() function to tell the motor to move 500 steps.

void setup()
{
// Change these to suit your stepper if you want
stepper.setMaxSpeed(100);
stepper.setAcceleration(20);
stepper.moveTo(500);
}

Inside the void loop function, we are checking if the motor reached it’s position or not. If it reached the position, it will bounce back. and if it didn’t reach it’s position yet, it will keep running.

void loop()
{
// If at the end of travel go to the other end
if (stepper.distanceToGo() ==0)
stepper.moveTo(-stepper.currentPosition());
stepper.run();
}

Camera Slider Full Wireless Control

We have done great things so far. Let’s continue! The next step after testing everything, is to work on the mobile app that we will use to control the camera slider movement and send the orders to it. Also, we need to work on the Arduino code that will receive the data from the mobile app and according to these data it will take some actions like moving the motor, changing speed, acceleration, and so on…

Building The Mobile App

To build the mobile app, I used the MIT App inventor tool that allows you to create mobile apps that run on any Android smartphone. The tool is pretty simple since you only drag and drop some pre-made code blocks to build the logic of your program, also you use some premade blocks to build the app user interface. You can access the source of the mobile app from the link down below. Feel free to edit and share, it’s open-source. Mobile App Source

The image down below, a brief explanation for each button function and how it works.

That mobile app will communicate with the Cairo camera slider wirelessly over the Bluetooth communication. So, the next step is to connect a Bluetooth module to the last circuit we built before and upload some lines of code to the Arduino board to be able to establish the communication between the mobile app and the Cairo camera slider.

Wiring Diagram

It’s the time to connect all things together, previously we connected the stepper motor, stepper motor driver, Arduino UNO, and the battery together and tested the circuit and it worked fine. Now, and after building the mobile app, we need to connect the HC-05 Bluetooth module to our circuit.

To make it wireless we will use the HC-05 Bluetooth module which has wide use, it can set as slave or master as well (unlike the HC-06 module which can work only as a slave) which means that you can make a Bluetooth connection between two different Arduino boards. the HC-05 Bluetooth module is an SPP (Serial Port Protocol) module, which means that it communicates with the Arduino board via the Serial communication. You only need to connect the Tx and the Rx pins between the HC-05 module and the Arduino UNO board.

  • Tx(Arduino) --> Rx(HC-05)
  • Rx(Arduino) --> Tx(HC-05)
  • 5V(Arduino) --> VCC(HC-05)
  • GNND(Arduino) --> GND(HC-05)

Schematic and PCB Fabrication

Man! I don’t like breadboarding a big circuit like this. So, I designed a super pretty Arduino UNO shield PCB board that keeps all my components in place without worrying about the jumper wires or even the connections. All you need to do is to place your component on the Arduino shield PCB, insert the HC-05 Bluetooth module, A4988 stepper motor driver, and the battery in their places. and install the shield on top of the Arduino board. that’s it!

I fabricated my PCB at PCBWay the quality was very good, in a few days the package arrived in Egypt safely. and I paid just 5$ for the fabrication which is amazing. The coolest thing that I was able to check the order fabrication and processing status online on my account panel and track everything happening to my baby board like I was there inside the factory.

you can download the PCB design source files or even ordering the Cairo Camera Slider Arduino Shield PCB from the PCBWay website. PCB Source Files &Ordering




Arduino Code And Bluetooth Communication

/*
TODO::Update the arduino program to Make the user able to choose the motor driver micro stepping mode. find and equation that helps to automatically adjust the the "steps" variable value.
TODO::update the mobile app to ask the user on the beginning only about the [homing position(done), microstepping mode].
TODO::Update the arduino program to make the code only iterates around the "homing position" &"microstepping mode" only once on the void setup() function.

DATA::left arrow button sends --> 1.
DATA::right arrow button sends --> 2.
DATA::stop button sends --> 3.

DATA::rail length (1cm - 1000cm) --> (201 - 1200).

DATA::motor acceleration spinner Very High --> 14.
DATA::motor acceleration spinner High --> 11
DATA::motor acceleration spinner Medium --> 12
DATA::motor acceleration spinner Low --> 13
DATA::motor acceleration spinner Very Low --> 15

DATA::motor speed slider (1 step/sec. - 4000 step/sec.) --> (5001 - 9000).

DATA::delay start checkbox is true --> 7.
DATA::delay start checkbox is false --> 8.

DATA::left end homing --> 16.
DATA::right end homing --> 17.

DATA::Smooth movement Type --> 18.
DATA::Very Smooth movement Type --> 19.

1301 --> 2300
*/

#include
#include

#define stepPin 2
#define dirPin 3

bool homingPositionFlag =false;
int startupSetupFlag =0;
bool delayedStart =false;

int incomingData =0;
int movementDistance =50;
long steps =0; //50cm rail by default @1/8 microstepping.
int microStepResolution =0; //4 or 16
long railLength =0;
int sliderSpeed =10;

AccelStepper stepper(AccelStepper::DRIVER, stepPin, dirPin); //create an object. the pin "2" is the step pin, "3" is the direction pin.

void setup() {
pinMode(stepPin, OUTPUT);
pinMode(dirPin, OUTPUT);
Serial.begin(9600);

stepper.setMaxSpeed(10.00); //The fastest motor speed that can be reliably supported is about 4000 steps per second at a clock frequency of 16 MHz on Arduino such as Uno
stepper.setAcceleration(500.00); //1600 (40%) (Medium Acceleration rate)

while (startupSetupFlag <3) {
if (Serial.available()> 1) {
unsigned int dataOne =Serial.read();
unsigned int dataOne1 =Serial.read();
unsigned int incomingData =(dataOne1 * 256) + dataOne;

//**************************************************************Motor Homing Part**************************************************
if (incomingData ==16) { //left end homing position.
stepper.setCurrentPosition(steps);
homingPositionFlag =false;
startupSetupFlag++;
} else if (incomingData ==17) { //right end homing position.
stepper.setCurrentPosition(-(steps));
homingPositionFlag =true;
startupSetupFlag++;
}
//**************************************************************microstep resolution Part**************************************************
if (incomingData ==18) {
microStepResolution =4; //50cm rail length @1/4 microstep resolution.
startupSetupFlag++;
} else if (incomingData ==19) {
microStepResolution =16; //50cm rail length @1/16 microstep resolution.
startupSetupFlag++;
}

if (incomingData>=1301 &&incomingData <=2300) {
railLength =incomingData - 1300; //from raw data to cm.
if (microStepResolution ==4) {
steps =((6100L * railLength) / 50L);
startupSetupFlag++;
}
else if (microStepResolution ==16) {
steps =((25000L * railLength) / 50L);
startupSetupFlag++;
}
}
}
//Serial.println(startupSetupFlag);
}
/*
* *********** *********** **********For Debugging Purposes* *********** *********** **********
Serial.print("rail length:");
Serial.print(railLength);
Serial.print(" number of steps:");
Serial.print(steps);
Serial.print(" Homing position:");
Serial.print(stepper.currentPosition());
Serial.print(" microstep resolution:");
Serial.println(microStepResolution);*/
}

void loop() {

if (Serial.available()> 1) {

unsigned int dataOne =Serial.read();
unsigned int dataOne1 =Serial.read();
unsigned int incomingData =(dataOne1 * 256) + dataOne;
//Serial.print("raw data:");
//Serial.println(incomingData);

//**************************************************************Motor Control Part**************************************************
if (incomingData ==1 &&stepper.isRunning() ==false &&stepper.currentPosition() !=6050 &&homingPositionFlag ==true) {
if (delayedStart ==true) { //use millis to delay 15 seconds.
delay(15000); //wait 15 seconds.
}
stepper.setCurrentPosition(0);
stepper.moveTo(steps); //from end to end (@ 1/4 step).
homingPositionFlag =false;

/*Serial.print("rail length:");
Serial.print(railLength);
Serial.print(" number of steps:");
Serial.print(steps);
Serial.print(" Homing position:");
Serial.print(stepper.currentPosition());
Serial.print(" microstep resolution:");
Serial.println(microStepResolution);*/
}

else if (incomingData ==2 &&stepper.isRunning() ==false &&stepper.currentPosition() !=-6050 &&homingPositionFlag ==false) {
if (delayedStart ==true) { //use millis to delay 15 seconds.
delay(15000); //wait 15 seconds.
}
stepper.setCurrentPosition(0);
stepper.moveTo(-(steps)); //from end to end (@ 1/4 step).
homingPositionFlag =true;

/*Serial.print("rail length:");
Serial.print(railLength);
Serial.print(" number of steps:");
Serial.print(steps);
Serial.print(" Homing position:");
Serial.print(stepper.currentPosition());
Serial.print(" microstep resolution:");
Serial.println(microStepResolution);*/
}

else if (incomingData ==3 &&stepper.isRunning() ==true) {
homing();
}

//**************************************************************Set Max. Speed Part**************************************************
else if (incomingData>=5001 &&incomingData <=9000) {
sliderSpeed =incomingData - 5000;
stepper.setMaxSpeed(sliderSpeed);
}

//**************************************************************Set Delayed Start Part**************************************************
else if (incomingData ==7) { //delayed start (15 seconds) is checked "true"
delayedStart =true;
}
else if (incomingData ==8) { //delayed start (15 seconds) is not checked "false"
delayedStart =false;
}

//**************************************************************Set movement distance Part**************************************************
else if (incomingData>=201 &&incomingData <=1200) { //convertin from rail length into number of steps. (upto 10 meters)
movementDistance =incomingData - 200; //from raw data to cm.
if (microStepResolution ==4) {
steps =((6100L * movementDistance) / 50L);
}
else if (microStepResolution ==16) {
steps =((25000L * movementDistance) / 50L);
}
/*Serial.print("rail length:");
Serial.print(movementDistance);
Serial.print(" number of steps:");
Serial.println(steps);*/
}

//**************************************************************Set Acceleration Part**************************************************
else if (incomingData ==11 &&stepper.isRunning() ==false) { //HIGH
stepper.setAcceleration(3000);
}

else if (incomingData ==12 &&stepper.isRunning() ==false) { //Medium
stepper.setAcceleration(1000);
}

else if (incomingData ==13 &&stepper.isRunning() ==false) { //Low
stepper.setAcceleration(500);
}

else if (incomingData ==14 &&stepper.isRunning() ==false) { //Very High
stepper.setAcceleration(4000);
}

else if (incomingData ==15 &&stepper.isRunning() ==false) { //Very Low
stepper.setAcceleration(10);
}
}
stepper.run();
}

void homing() {
if (stepper.currentPosition()> 0) {
homingPositionFlag =true;
} else {
homingPositionFlag =false;
}
stepper.moveTo(0);
}

Code Logic

We’re using the amazing AccelStepper Arduino library that provides an object-oriented interface for 2, 3, 4 pins stepper motors to control it’s movement precisely.

#define stepPin 2
#define dirPin 3

bool homingPositionFlag =false;

int startupSetupFlag =0;
bool delayedStart =false;

int incomingData =0;
int movementDistance =50;

long steps =0; //50cm rail by default @1/8 microstepping.
int microStepResolution =0; //4 or 16

long railLength =0;
int sliderSpeed =10;

AccelStepper stepper(AccelStepper::DRIVER, stepPin, dirPin); //create an object. the pin "2" is the step pin, "3" is the direction pin.

when you open the mobile app and get connected to the Cairo camera slider it will ask you about the micro-stepping mode that you set the A4988 motor driver to work at. it’s very important to choose the correct micro-stepping mode. The Cairo camera slider only supports the 1/4 and 1/16 micro-step resolution. If you chose a wrong micro-step mode it will affect the distance calculations causing the camera carriage to hit the slider limits. So, be careful!

  • 1/4 --> Smooth.
  • 1/16 --> Very Smooth.
//**************************************************************microstep resolution Part**************************************************
if (incomingData ==18) {
microStepResolution =4; //50cm rail length @1/4 microstep resolution.
startupSetupFlag++;

} else if (incomingData ==19) {
microStepResolution =16; //50cm rail length @1/16 microstep resolution.
startupSetupFlag++;
}

It sets the camera slider homing if it’s left or right side homing. the homing position, once you click on right or left side homing a specific piece of data will get sent from the mobile app to the Arduino board according to the homing position that you have chosen.

void setup() {
pinMode(stepPin, OUTPUT);
pinMode(dirPin, OUTPUT);
Serial.begin(9600);

stepper.setMaxSpeed(10.00); //The fastest motor speed that can be reliably supported is about 4000 steps per second at a clock frequency of 16 MHz on Arduino such as Uno
stepper.setAcceleration(500.00); //1600 (40%) (Medium Acceleration rate)

while (startupSetupFlag <3) {
if (Serial.available()> 1) {
unsigned int dataOne =Serial.read();
unsigned int dataOne1 =Serial.read();
unsigned int incomingData =(dataOne1 * 256) + dataOne;

//**************************************************************Motor Homing Part**************************************************
if (incomingData ==16) { //left end homing position.
stepper.setCurrentPosition(steps);
homingPositionFlag =false;
startupSetupFlag++;
}
else if (incomingData ==17) { //right end homing position.
stepper.setCurrentPosition(-(steps));
homingPositionFlag =true;
startupSetupFlag++;
}

now it sets how many steps should the stepper motor moves without hitting the camera carriage with the camera slider right or left legs. it reads and saves the rail length according to the value that the user enters in the mobile app. So, depending on the micro-step resolution that the user selected before, and the rail length I can calculate the number of steps that the motor should rotate to reach the limits of the slider rail without hitting the right or left legs.

if (incomingData>=1301 &&incomingData <=2300) {
railLength =incomingData - 1300; //from raw data to cm.
if (microStepResolution ==4) {
steps =((6100L * railLength) / 50L);
startupSetupFlag++;
}
else if (microStepResolution ==16) {
steps =((25000L * railLength) / 50L);
startupSetupFlag++;
}
}
}
//Serial.println(startupSetupFlag);
}

inside the loop function, it reads the mobile app incoming data and according to these data it takes different actions, like moving the stepper motor clockwise, moving anti-clockwise, stop and return back to the starting point, and changing the traveling speed, so on…

void loop() {

if (Serial.available()> 1) {

unsigned int dataOne =Serial.read();
unsigned int dataOne1 =Serial.read();
unsigned int incomingData =(dataOne1 * 256) + dataOne;
//Serial.print("raw data:");
//Serial.println(incomingData);

//**************************************************************Motor Control Part**************************************************
if (incomingData ==1 &&stepper.isRunning() ==false &&stepper.currentPosition() !=6050 &&homingPositionFlag ==true) {
if (delayedStart ==true) { //use millis to delay 15 seconds.
delay(15000); //wait 15 seconds.
}
stepper.setCurrentPosition(0);
stepper.moveTo(steps); //from end to end (@ 1/4 step).
homingPositionFlag =false;

/*Serial.print("rail length:");
Serial.print(railLength);
Serial.print(" number of steps:");
Serial.print(steps);
Serial.print(" Homing position:");
Serial.print(stepper.currentPosition());
Serial.print(" microstep resolution:");
Serial.println(microStepResolution);*/
}

else if (incomingData ==2 &&stepper.isRunning() ==false &&stepper.currentPosition() !=-6050 &&homingPositionFlag ==false) {
if (delayedStart ==true) { //use millis to delay 15 seconds.
delay(15000); //wait 15 seconds.
}
stepper.setCurrentPosition(0);
stepper.moveTo(-(steps)); //from end to end (@ 1/4 step).
homingPositionFlag =true;

/*Serial.print("rail length:");
Serial.print(railLength);
Serial.print(" number of steps:");
Serial.print(steps);
Serial.print(" Homing position:");
Serial.print(stepper.currentPosition());
Serial.print(" microstep resolution:");
Serial.println(microStepResolution);*/
}

else if (incomingData ==3 &&stepper.isRunning() ==true) {
homing();
}

//**************************************************************Set Max. Speed Part**************************************************
else if (incomingData>=5001 &&incomingData <=9000) {
sliderSpeed =incomingData - 5000;
stepper.setMaxSpeed(sliderSpeed);
}

//**************************************************************Set Delayed Start Part**************************************************
else if (incomingData ==7) { //delayed start (15 seconds) is checked "true"
delayedStart =true;
}
else if (incomingData ==8) { //delayed start (15 seconds) is not checked "false"
delayedStart =false;
}

//**************************************************************Set movement distance Part**************************************************
else if (incomingData>=201 &&incomingData <=1200) { //convertin from rail length into number of steps. (upto 10 meters)
movementDistance =incomingData - 200; //from raw data to cm.
if (microStepResolution ==4) {
steps =((6100L * movementDistance) / 50L);
}
else if (microStepResolution ==16) {
steps =((25000L * movementDistance) / 50L);
}
/*Serial.print("rail length:");
Serial.print(movementDistance);
Serial.print(" number of steps:");
Serial.println(steps);*/
}

//**************************************************************Set Acceleration Part**************************************************
else if (incomingData ==11 &&stepper.isRunning() ==false) { //HIGH
stepper.setAcceleration(3000);
}

else if (incomingData ==12 &&stepper.isRunning() ==false) { //Medium
stepper.setAcceleration(1000);
}

else if (incomingData ==13 &&stepper.isRunning() ==false) { //Low
stepper.setAcceleration(500);
}

else if (incomingData ==14 &&stepper.isRunning() ==false) { //Very High
stepper.setAcceleration(4000);
}

else if (incomingData ==15 &&stepper.isRunning() ==false) { //Very Low
stepper.setAcceleration(10);
}
}
stepper.run();
}

void homing() {
if (stepper.currentPosition()> 0) {
homingPositionFlag =true;
} else {
homingPositionFlag =false;
}
stepper.moveTo(0);
}

Cairo Camera Slider User Guide &troubleshooting

After connecting the 12V power source to the Arduino UNO board that distributes power to the Cairo camera slider Arduino shield as well, turn on the Bluetooth on your mobile, search for new devices, pair with the HC-05 device, and open the mobile app then press on the “Press here to connect with Cairo camera slider” button. It will show up the menu of the paired Bluetooth devices, select the HC-05 Bluetooth device.

After connecting successfully with the Control board, the mobile app will ask you some questions to set up some parameters. First question will ask you about the micro-step resolution of the stepper motor driver if it’s smooth(1/4 micro-step), or very smooth(1/16 micro-step). select the mode According to the micro-stepping resolution mode that you set the A4988 driver at. If you selected a wrong mode The Cairo camera slider will not work correctly.

Then, it will ask you about the aluminum rail length that you are using in your camera slider. Enter the distance in CM. in my case I’m using a 50cm rail length.

Lastly, it will ask you about the camera carriage homing position, It’s very important to place the camera carriage on one of the two rail ends, the right end or the left end. In my case, the camera carriage is on the left end. So, I selected the left end homing.

If you started the Cairo camera slider and the camera carriage is on the middle of the rail or not on one of the two rail ends it will cause the carriage to hit the limits when it moves.

After you finish the set-up process, It will show you the parameters that you have set. And once you click OK, you will be ready to play around with your lovely Cairo camera slider.

Cairo Camera Slider In-Action


Code

  • Cairo Camera Slider Final Code
Cairo Camera Slider Final CodeArduino
/* TODO::Update the arduino program to Make the user able to choose the motor driver micro stepping mode. find and equation that helps to automatically adjust the the "steps" variable value. TODO::update the mobile app to ask the user on the beginning only about the [homing position(done), microstepping mode]. TODO::Update the arduino program to make the code only iterates around the "homing position" &"microstepping mode" only once on the void setup() function. DATA::left arrow button sends --> 1. DATA::right arrow button sends --> 2. DATA::stop button sends --> 3. DATA::rail length (1cm - 1000cm) --> (201 - 1200). DATA::motor acceleration spinner Very High --> 14. DATA::motor acceleration spinner High --> 11 DATA::motor acceleration spinner Medium --> 12 DATA::motor acceleration spinner Low --> 13 DATA::motor acceleration spinner Very Low --> 15 DATA::motor speed slider (1 step/sec. - 4000 step/sec.) --> (5001 - 9000). DATA::delay start checkbox is true --> 7. DATA::delay start checkbox is false --> 8. DATA::left end homing --> 16. DATA::right end homing --> 17. DATA::Smooth movement Type --> 18. DATA::Very Smooth movement Type --> 19. 1301 --> 2300*/#include #include #define stepPin 2#define dirPin 3bool homingPositionFlag =false;int startupSetupFlag =0;bool delayedStart =false;int incomingData =0;int movementDistance =50;long steps =0; //50cm rail by default @1/8 microstepping.int microStepResolution =0; //4 or 16long railLength =0;int sliderSpeed =10;AccelStepper stepper(AccelStepper::DRIVER, stepPin, dirPin); //create an object. the pin "2" is the step pin, "3" is the direction pin.void setup() { pinMode(stepPin, OUTPUT); pinMode(dirPin, OUTPUT); Serial.begin(9600); stepper.setMaxSpeed(10.00); //The fastest motor speed that can be reliably supported is about 4000 steps per second at a clock frequency of 16 MHz on Arduino such as Uno stepper.setAcceleration(500.00); //1600 (40%) (Medium Acceleration rate) while (startupSetupFlag <3) { if (Serial.available()> 1) { unsigned int dataOne =Serial.read(); unsigned int dataOne1 =Serial.read(); unsigned int incomingData =(dataOne1 * 256) + dataOne; //**************************************************************Motor Homing Part************************************************** if (incomingData ==16) { //left end homing position. stepper.setCurrentPosition(steps); homingPositionFlag =false; startupSetupFlag++; } else if (incomingData ==17) { //right end homing position. stepper.setCurrentPosition(-(steps)); homingPositionFlag =true; startupSetupFlag++; } //**************************************************************microstep resolution Part************************************************** if (incomingData ==18) { microStepResolution =4; //50cm rail length @1/4 microstep resolution. startupSetupFlag++; } else if (incomingData ==19) { microStepResolution =16; //50cm rail length @1/16 microstep resolution. startupSetupFlag++; } if (incomingData>=1301 &&incomingData <=2300) { railLength =incomingData - 1300; //from raw data to cm. if (microStepResolution ==4) { steps =((6100L * railLength) / 50L); startupSetupFlag++; } else if (microStepResolution ==16) { steps =((25000L * railLength) / 50L); startupSetupFlag++; } } } //Serial.println(startupSetupFlag); } /* * *********** *********** **********For Debugging Purposes* *********** *********** ********** Serial.print("rail length:"); Serial.print(railLength); Serial.print(" number of steps:"); Serial.print(steps); Serial.print(" Homing position:"); Serial.print(stepper.currentPosition()); Serial.print(" microstep resolution:"); Serial.println(microStepResolution);*/}void loop() { if (Serial.available()> 1) { unsigned int dataOne =Serial.read(); unsigned int dataOne1 =Serial.read(); unsigned int incomingData =(dataOne1 * 256) + dataOne; //Serial.print("raw data:"); //Serial.println(incomingData); //**************************************************************Motor Control Part************************************************** if (incomingData ==1 &&stepper.isRunning() ==false &&stepper.currentPosition() !=6050 &&homingPositionFlag ==true) { if (delayedStart ==true) { //use millis to delay 15 seconds. delay(15000); //wait 15 seconds. } stepper.setCurrentPosition(0); stepper.moveTo(steps); //from end to end (@ 1/4 step). homingPositionFlag =false; /*Serial.print("rail length:"); Serial.print(railLength); Serial.print(" number of steps:"); Serial.print(steps); Serial.print(" Homing position:"); Serial.print(stepper.currentPosition()); Serial.print(" microstep resolution:"); Serial.println(microStepResolution);*/ } else if (incomingData ==2 &&stepper.isRunning() ==false &&stepper.currentPosition() !=-6050 &&homingPositionFlag ==false) { if (delayedStart ==true) { //use millis to delay 15 seconds. delay(15000); //wait 15 seconds. } stepper.setCurrentPosition(0); stepper.moveTo(-(steps)); //from end to end (@ 1/4 step). homingPositionFlag =true; /*Serial.print("rail length:"); Serial.print(railLength); Serial.print(" number of steps:"); Serial.print(steps); Serial.print(" Homing position:"); Serial.print(stepper.currentPosition()); Serial.print(" microstep resolution:"); Serial.println(microStepResolution);*/ } else if (incomingData ==3 &&stepper.isRunning() ==true) { homing(); } //**************************************************************Set Max. Speed Part************************************************** else if (incomingData>=5001 &&incomingData <=9000) { sliderSpeed =incomingData - 5000; stepper.setMaxSpeed(sliderSpeed); } //**************************************************************Set Delayed Start Part************************************************** else if (incomingData ==7) { //delayed start (15 seconds) is checked "true" delayedStart =true; } else if (incomingData ==8) { //delayed start (15 seconds) is not checked "false" delayedStart =false; } //**************************************************************Set movement distance Part************************************************** else if (incomingData>=201 &&incomingData <=1200) { //convertin from rail length into number of steps. (upto 10 meters) movementDistance =incomingData - 200; //from raw data to cm. if (microStepResolution ==4) { steps =((6100L * movementDistance) / 50L); } else if (microStepResolution ==16) { steps =((25000L * movementDistance) / 50L); } /*Serial.print("rail length:"); Serial.print(movementDistance); Serial.print(" number of steps:"); Serial.println(steps);*/ } //**************************************************************Set Acceleration Part************************************************** else if (incomingData ==11 &&stepper.isRunning() ==false) { //HIGH stepper.setAcceleration(3000); } else if (incomingData ==12 &&stepper.isRunning() ==false) { //Medium stepper.setAcceleration(1000); } else if (incomingData ==13 &&stepper.isRunning() ==false) { //Low stepper.setAcceleration(500); } else if (incomingData ==14 &&stepper.isRunning() ==false) { //Very High stepper.setAcceleration(4000); } else if (incomingData ==15 &&stepper.isRunning() ==false) { //Very Low stepper.setAcceleration(10); } } stepper.run();}void homing() { if (stepper.currentPosition()> 0) { homingPositionFlag =true; } else { homingPositionFlag =false; } stepper.moveTo(0);}

Custom parts and enclosures

Cairo Camera Slider STLs
CAD file on thingiverse.com

Schematics


Herstellungsprozess

  1. Kamera
  2. Kameraobjektiv
  3. BrickPi-Bookreader
  4. Arduino Spybot
  5. FlickMote
  6. Selbstgemachter Fernseher B-Gone
  7. Hauptuhr
  8. Finde mich
  9. Arduino-Power
  10. Die Kamera nimmt Bilder des Inneren fester Objekte auf