Advertisement
  1. Code
  2. Coding Fundamentals

Kontrol Gerakan Dengan Arduino: Mengarahkan Slider Kamera

Scroll to top
Read Time: 22 min

() translation by (you can also view the original English article)

Ketersediaan motor dan driver stepper murah dewasa ini memungkinkan banyak kesempatan untuk bereksperimen di luar proyek pemotongan dan pencetakan 2D / 3D yang lebih mahal dan rumit.

Untuk proyek ini, saya akan mengambil slider kamera OpenBuilds (lihat video dalam Membangun Slider Video Dasar Dengan Open Source CNC Parts) dan menguncinya. Saya juga akan membuat sistem mandiri untuk mengendalikan motor.

Tutorial ini secara khusus mencakup pembuatan perangkat keras, tetapi terutama membangun GUI LCD 16x2 yang belum sempurna menggunakan pustaka LiquidCrystal dan sistem menu sederhana untuk ditampilkan, diikuti oleh cara kerja driver A4988 dan cara mengendalikannya dengan Arduino.

Proyek ini berat di perulangan dan langkah-langkah, dan sementara keseluruhan proyek lebih menengah, saya sudah mencoba menjelaskannya sedemikian rupa sehingga pemula dapat berdiri dan berjalan relatif cepat.

Daftar perlengkapan

Komponen

Part

Alat-alat

  • Komputer dengan Arduino IDE (saya menggunakan Win7, Arduino 1.0.5 r2)
  • Besi solder dengan ujung pahat kecil, solder, dll
  • 2.5mm kunci allen untuk sekrup M5
  • 2mm kunci allen untuk sekrup M3
  • 1.5mm kunci allen untuk mengatur sekrup di pulley GT2
  • multimeter untuk troubleshooting dan penyesuaian saat ini
  • Tang sempit untuk mengencangkan di ruang kecil

Ikhtisar Fungsional

Saya akan membahas menambahkan motor dan pulley ke slider, merangkai sabuk di sekitar dan mengencangkan semuanya. Ini adalah modifikasi yang sederhana.

Kemudian saya akan membahas cara menyusun kit Pololu A4988 Black Edition dan cara memasangnya di papan breadboard bersama dengan semua papan eksternal lainnya, serta plywood enclosure sederhana yang saya ketuk bersama dalam beberapa menit untuk daya 12V saya persediaan (tercantum di atas) untuk mencegah guncangan ketika terminal kabel terkena.

Tersamping sehingga tetap cukup besar sehingga nomor pin masih terlihat!

Menu memungkinkan input jarak untuk bepergian, waktu perjalanan, jumlah langkah untuk bepergian dan arah perjalanan. Di akhir setiap langkah, slider berhenti sementara kamera dipicu.

Memodifikasi Slider

Langkah 1: Merakit Motor

OpenBuilds V-Slot Actuator End Mount memiliki lubang NEMA 17 dimensi di dalamnya, sehingga empat sekrup kepala topi M3 30mm semuanya diperlukan untuk memasang motor ke sana.

The OpenBuilds V-Slot Actuator End MountThe OpenBuilds V-Slot Actuator End MountThe OpenBuilds V-Slot Actuator End Mount
OpenBuilds V-Slot Actuator End Mount

Pastikan puli 20 gigi GT2 ada di dalam dudukan sebelum anda memasukkan poros motor, karena tunggangannya tidak cukup lebar untuk ditambahkan setelahnya. Setelah motor dikencangkan pada bagian bawah, kencangkan sekrup yang disetel dengan salah satunya terhadap bagian datar poros motor, memastikan bahwa gigi langsung sejajar dengan pusat dari seluruh unit ekstrusi.

Langkah 2: Kit Idler Pulley

Kit idler pulley bekerja sama seperti kit roda, dan slot ke  Actuator Mount ujung yang berlawanan:

Kit idler pulley

Langkah 3: Belting Up

Porsi sabuk melalui pusat slot V sejajar dengan pulleys, memastikan gigi menghadap ke atas

Kemudian beri porsi di atas dan di atas dua katrol dan bawa kembali ke tengah ke pelat bangun pengangkut.

Feeding the beltFeeding the beltFeeding the belt
Gigi saling mencengkeram.

Di sini anda membungkus satu sisi melalui slot sabuk dan klem, atau mengikatnya dengan zip, kemudian menggunakannya untuk mengencangkan seluruh sabuk melalui seluruh sistem sebelum menghubungkan sisi yang lain. Tidak terlalu ketat bagi motor untuk berbelok, tetapi tidak cukup longgar untuk melewati gigi pada puli drive!

Merakit Elektronik

Langkah 1: Merakit Driver Stepper

Pololu A4988 Black Edition Stepper Driver Motor (secara teknis A4988 carrier board-A4988 adalah chip itu sendiri) biasanya datang dalam bentuk kit, yang berarti bahwa header harus disolder. Karena ini adalah komponen daya, meskipun tidak menggerakkan unit pada kapasitas maksimumnya, ada baiknya untuk menambahkan heatsink untuk membantu meningkatkan masa pakainya.

Pecahkan baris header menjadi dua untuk memiliki dua baris delapan. Masukkan ini ke dalam lubang berlubang di papan, dan kemudian masukkan ini dengan hati-hati ke papan breadboard. Solder pin di tempatnya sementara papan breadboard memegang segala yang bagus dan tegak lurus.

Putting together the Stepper DriverPutting together the Stepper DriverPutting together the Stepper Driver
Menyatukan Driver Stepper

Setelah ini selesai, potong sudut heatsink self-stick kecil menggunakan gergaji besi atau scrollsaw (hati-hati, di jepitan!) Untuk me-mount ke IC A4988.

Cut off the corner of a small self-stick heatsinkCut off the corner of a small self-stick heatsinkCut off the corner of a small self-stick heatsink
Potong sudut dari heatsink tongkat kecil

Langkah 2: Breadboard-Mount Komponen

Sekarang semuanya harus di-mount ke breadboards sehingga dapat dihubungkan bersama menjadi cicuit yang berfungsi. Saya menggunakan papan terpisah untuk setiap bagian demi kejelasan gambar, tetapi merasa bebas untuk memasukkan semuanya ke dalam satu papan jika anda mau.

Perisai papan tombol LCD tidak dapat dipasang ke papan, berkat pilihan aneh Arduino untuk mematuhi cacat desain daripada memenuhi standar. Ini akan disimpan terpisah, meskipun mengacaukannya ke sepotong kayu atau sesuatu untuk melindungi pin mungkin bukan ide yang buruk.

Rangkaian pemicu kamera pada yang paling sederhana terdiri dari resistor, transistor dan sub-mini plug 2.5mm TRS. Saya telah menambahkan LED yang akan berkedip ketika pin pemicu berduri tinggi, dan jack mini TRS 3,5mm untuk memungkinkan fleksibilitas.

Jika anda membeli komponen untuk membangun ini, soket 3,5 mm yang dirancang untuk papan pitch 0,1 "akan menjadi ide yang bagus, tetapi saya adalah dari tumpukan yang mengumpulkan jadi saya sudah menyolder konektor ke itu sebagai gantinya.

Letakkan semuanya, siap untuk mentransfer semuanya.

Langkah 3: Pengkabelan Semuanya Bersama

Saatnya untuk mengambil semua kabel jumper. Memiliki cukup untuk menjaga kode warna akan membuat hidup lebih mudah ketika mengatasi masalah. Lihat diagram sirkuit di bagian atas jika uraian berikut membingungkan anda di titik mana pun.

Wiring Everything TogetherWiring Everything TogetherWiring Everything Together
Pengkabelan Semuanya Bersama

Pertama pasang LCD. Ambil 10 jumper female dan hubungkan ke pin perisai berikut: pin digital 4-9, pin ulang daya bus (jika anda ingin menggunakan tombol reset LCD), 5V & salah satu GND.

Jika anda memiliki jumper female-ke-male, anda dapat meninggalkannya di sana. Jika tidak, hubungkan jumper male- ke ujung yang lain dari female- untuk menghubungkan mereka ke soket header Arduino yang sesuai. Jika anda memiliki perisai papan tombol LCD yang telah melewati header perempuan yang dipasang di atas, anda dapat melewati langkah ini karena perisai anda tidak memblokir apa pun.

Selanjutnya, papan Pololu A4988. Ini membutuhkan delapan jumper di satu sisi, saya telah menggunakan hitam dan merah untuk logika / kekuatan motor di ujung easch, dan merah / hijau / biru / kuning di tengah empat untuk menyesuaikan dengan lead servo motor stepper.

Pin daya logika masuk ke 3.3V pada arduino, karena LCD di atas menggunakan pin 5V. Daya motor mengarah ke catu daya 12V Anda. Di sisi lain, dekat chip A4988, saya menggunakan biru dan oranye untuk STP dan DIR masing-masing untuk kontras dengan warna yang relatif seragam di tempat lain. Mereka pergi ke Arduino pin 11 dan 12 masing-masing, kecuali anda memodifikasi kode. Kemudian RST dan SLP pendek bersama untuk menjaga agar papan tetap aktif; Saya telah menggunakan memimpin putih di sini.

When youre done it should look something like thisWhen youre done it should look something like thisWhen youre done it should look something like this
Setelah selesai, seharusnya terlihat seperti ini.

Akhirnya memasang rangkaian sakelar pemicu kamera. Di sini kabel-kabel hitam itu digaris bawahi - kabel baris A ke Arduino, kabel C baris ke soket 3,5 mm. Warnanya kuning ke Arduino pin 13 (jadi ada indikator LED di papan juga di saklar!), Dan kabel merah ke sisi lain soket 3,5mm (atau konektor 2.5mm jika Anda akan rute itu).

Pasang motor stepper ke dalam kabel berwarna sesuai dengan diagram papan A4988 dan datasheet stepper anda. Bagi saya, itu seperti ini:

Like the button reader the test rotation sketch is included in the zip up topLike the button reader the test rotation sketch is included in the zip up topLike the button reader the test rotation sketch is included in the zip up top
Seperti pembaca tombol, sketsa rotasi tes disertakan dalam zip di bagian atas.

Perhatian: ingat bahwa kabel yang menyediakan daya ke motor mungkin akan menarik 1-2A pada tegangan yang anda pilih, jadi pastikan kabel yang digunakan diberi nilai untuk itu. Chip A4988 dan papan di sekitarnya mungkin menjadi panas! Potensiometer yang terpasang di papan memberikan batasan saat ini untuk melindungi A4988 dan motor, jadi pastikan anda mengaturnya dengan tepat sebelum digunakan menggunakan multimeter.

Menyiapkan Program

Setelah komponen dirakit, Anda dapat pindah ke pengkodean. Unduh zip yang disertakan dengan tutorial ini, atau periksa respositori GitHub ini jika anda mau. Saya akan menjelaskan bagaimana saya menggabungkannya sehingga anda dapat memahami alur program umum dan bagaimana modul bekerja bersama.

Langkah 1: Termasuk dan Definisi Dasar

Satu-satunya termasuk yang diperlukan untuk ini adalah library menulis LCD LiquidCrystal.h. Ini memberikan akses ke fungsi lcd.xxxx (). Ada pow () dalam program, dan saya menemukan bahwa termasuk matematika C ++ library.math.h tidak diperlukan karena beberapa fungsi yang paling bermanfaat termasuk dalam lingkungan Arduino, termasuk pow ().


1
#include <LiquidCrystal.h>

2
3
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);    //set LCD output pins

4
5
//define stepper driver pins

6
const int stp = 11;    //can't use pin 10 with the SS LCD as it's the backlight control. 

7
//if it goes low, backlight turns off!

8
const int dir = 12;
9
10
//define trigger pin

11
const int trig = 13;
12
13
//BUTTONS

14
//define button values

15
const int btnUp = 0;
16
const int btnDn = 1;
17
const int btnL = 2;
18
const int btnR = 3;
19
const int btnSel = 4;
20
const int btnNone = 5;
21
22
//define button-reading variables

23
int btnVal = 5;
24
int adcIn = 0;

Saya mengatur pin output LCD, pin output driver stepper, dan pin output pemicu kamera. Setelah antarmuka perangkat keras yang sebenarnya diatur, saya menambahkan variabel untuk acara tombol diikuti oleh fungsi membaca tombol, yang saya adaptasikan dari wiki DFRobot pada pelindung keypad LCD yang identik. Perhatikan bahwa SainSmart tidak menyediakan dokumentasi.

Langkah 2: Setup() Loop

Ini super straightfoward. Inisialasikan LCD dan pin output yang relevan, diikuti oleh layar selamat datang dasar, kemudian turun ke layar awal: opsi menu 1 dengan nilai-nilai memusatkan perhatian.

1
void setup() {
2
  lcd.begin(16, 2);               // initialise LCD lib full-screen

3
  lcd.setCursor(0,0);             // set cursor position

4
5
  pinMode(stp, OUTPUT);           //initialise stepper pins

6
  pinMode(dir, OUTPUT);
7
8
  pinMode(trig, OUTPUT);           //initialise trigger pin

9
  digitalWrite(trig, LOW);         //ensure trigger is turned off

10
11
  lcd.print("Welcome to");  //welcome screen

12
  lcd.setCursor(0,1);
13
  lcd.print("SliderCam v0.2!");
14
  delay(1000);
15
  lcd.clear();
16
  lcd.print(menuItemsTop[0]);
17
  delay(100);
18
  lcd.setCursor(0,1);
19
  for (int i = 0; i < 4; i++) {
20
    lcd.setCursor(i, 1);
21
    lcd.print(currentDistance[i]);
22
  }
23
  lcd.setCursor(4,1);
24
  lcd.print("mm(max 1300)");
25
}

Langkah 3: Monitor Tombol

Keuntungan di sini coding-bijaksana adalah bahwa peralatan tidak perlu melakukan apa-apa tanpa masukan pengguna. Yang berarti bahwa hal pertama hanya bisa menjadi lingkaran polling tombol abadi. Memanggil fungsi readLcdButtons () berulang-ulang sampai perubahan nilainya tidak berdampak negatif terhadap kinerja program, dan Anda tidak perlu khawatir meninggalkan pin interupsi yang tersedia.

1
void loop() {
2
  do {
3
    btnVal = readLcdButtons();      //continually read the buttons...

4
  } 
5
  while (btnVal==5);              //...until something is pressed
1
//declare button poll function

2
int readLcdButtons() {
3
  delay(90); //debounce delay, tuned experimentally. delay is fine as program shouldn't be doing anything else 

4
  //at this point anyway

5
  adcIn = analogRead(0); //read value from pin A0

6
7
  /*threshold values confirmed by experimentation with button calibration sketch returning the following ADC read values:

8
   right: 0

9
   up: 143

10
   down: 328

11
   left: 504

12
   select: 741

13
   */
14
15
  if (adcIn > 1000) return btnNone;
16
  if (adcIn < 50)   return btnR;
17
  if (adcIn < 250)  return btnUp;
18
  if (adcIn < 450)  return btnDn;
19
  if (adcIn < 650)  return btnL;
20
  if (adcIn < 850)  return btnSel;
21
22
  return btnNone; //if it can't detect anything, return no button pressed

23
}

ReadLcdButtons () memiliki penundaan 90ms untuk debounce tombol. Pada kenyataannya, ini bukan debounce, karena tidak mengambil kembali pengukuran ADC setelah waktu yang ditentukan, tetapi lebih sering polling tombol-tombol yang jarang untuk mendaftar lebih dari satu klik.

Ini mencapai hal yang sama dari pandangan UX praktis. Ini lebih dari tombol jajak pendapat setiap 90ms daripada terus-menerus, yang mengapa penggunaan delay () umumnya tidak dianggap praktik yang baik untuk tujuan debouncing, tetapi memperbaiki masalah (hanya setiap akhir menu yang dapat diakses).

Langkah 4: Screen Refresh

Setelah unit dapat bereaksi terhadap input, perlu ada cara untuk menampilkan reaksi tersebut.

Setelah mencoba pembaruan on-the-fly, saya memutuskan bahwa penyegaran layar yang konsisten seperti OS nyata lebih mudah untuk dikelola dalam upaya saya pada struktur modular yang dapat di-upgrade. Melakukan hal ini sesederhana membersihkan layar, kemudian membangun kembali berdasarkan parameter yang diketahui saat ini.

Ini terdengar rumit, tetapi dalam praktiknya membuat hidup jauh lebih mudah. Ini menghapus sejumlah besar perintah LCD dari tempat lain dalam program, dan menciptakan zona tipe-agnostik variabel yang sangat dipengaruhi oleh pembaruan program di luarnya.

Bagian penyegaran yang sebenarnya berevolusi untuk terdiri dari empat langkah berbeda:

Setel ulang parameter ...

1
//PRINT NEW SCREEN VALUES

2
  btnVal=btnNone;
3
  lcd.clear();

...cetak baris atas ...

1
lcd.setCursor(0, 0);
2
  lcd.print(menuItemsTop[currentMenuItem]);    //print top level menu item

cetak garis bawah, yang akan saya jelaskan nanti ...

1
 lcd.setCursor(0,1);
2
  switch (currentMenuItem) {
3
  case 0:
4
    {
5
      for (int i = 0; i < 4; i++) {
6
        lcd.setCursor(i, 1);
7
        lcd.print(currentDistance[i]);
8
      }
9
      break;
10
    }
11
12
  case 1:
13
    {
14
      for (int i = 0; i < 6; i++) {
15
        lcd.setCursor(i, 1);
16
        lcd.print(currentDuration[i]);
17
      }
18
      break;
19
    }
20
21
  case 2:
22
    {
23
      for (int i = 0; i < 4; i++) {
24
        lcd.setCursor(i, 1);
25
        lcd.print(currentSteps[i]);
26
      }
27
      break;
28
    }
29
30
  case 3:
31
    {
32
      if (travelDir == 0) lcd.print("From Motor");
33
      else lcd.print("To Motor");
34
      break;
35
    }
36
37
  case 4:
38
    {
39
      lcd.print("Stop!");
40
      break;
41
    }
42
  }  //end switch

... dan tambahkan perintah khusus layar dari atas apa yang sudah dicetak.

1
if (currentMenuItem==0){
2
    lcd.setCursor(4,1);
3
    lcd.print("mm(max 1300)");    //insert max carriage travel on slider used
4
  }
5
  if (currentMenuItem==1){
6
    lcd.setCursor(6,1);
7
    lcd.print("s(3600/hr)");
8
  }
9
  if (currentMenuLevel == 1) {
10
    lcd.setCursor(currentCursorPos, 1);
11
    lcd.blink();
12
  }
13
  else lcd.noBlink();

Membangun Menu: Judul Utama

Tentu saja, bagian penyegaran layar yang tepat tidak menulis sendiri, dan kita perlu mengetahui menu yang ditulis ke layar sebelum dapat diselesaikan. Judul utamanya mudah, karena tidak benar-benar berubah tergantung pada input pengguna. Ini berarti dapat berupa string array - secara teknis array pointer char, atau array array:

1
//MENU GUI

2
//define top-level menu item strings for numerical navigation

3
char* menuItemsTop[] = {
4
  "  01 Distance >", "< 02 Duration >", "< 03 Steps > ", "< 04 Direction >", "< 05 Go!"};
5
6
int currentMenuLevel = 0;      //top menu or submenu

7
int currentMenuItem = 0;       //x-axis position of menu selection

8
int currentCursorPos = 0;      //current lcd cursor position

9
int currentDistance[4] = {
10
  0, 0, 0, 0};
11
int currentDuration[6] = {
12
  0, 0, 0, 0, 0, 0};
13
int currentSteps[4] = {
14
  0, 0, 0, 1};

Ini berarti bahwa array menuItemsTop ini dapat dinavigasi hanya dengan mengubah nomor di dalam tanda kurung siku pada waktu penyegaran layar. Yang terjadi begitu saja, karena semuanya nol-indeks, untuk melacak identik dengan integer currentMenuItem.

Memanipulasi currentMenuItem pada event tombol memungkinkan kita navigasi satu dimensi, jadi ketika Anda melihat menuItemsTop [currentMenuItem] itu jelas judul menu saat ini.

1
if (currentMenuLevel==0) {
2
    switch (btnVal){
3
    case  btnL:
4
      {
5
        if (currentMenuItem == 0) break;      //can't go left from here

6
        else currentMenuItem--;
7
        break;    
8
      }
9
10
    case  btnR:
11
      {
12
        if (currentMenuItem == 4) break;      //can't go right from here

13
        else  currentMenuItem++;
14
        break;
15
      }
16
17
    case  btnSel:
18
      {
19
        currentMenuLevel++;
20
        if (currentCursorPos > 3 && (currentMenuItem == 0 || currentMenuItem == 2)) currentCursorPos = 3; //don't go off the end of the numbers for the 4-digit numbers

21
        if (currentCursorPos > 0 && (currentMenuItem > 2)) currentCursorPos = 0; // set blinking cursor to left for text-based options

22
        if (currentMenuItem == 4) {
23
          motion = 1;
24
          motionControl();
25
          break;
26
        }
27
      } 
28
    } //end of switch

29
  } //end of level 0

Jadi Anda dapat bergerak ke kiri dan kanan, dan masuk ke menu, atau dalam kasus Go! kemudian kontrol gerak diaktifkan. Itu saja yang dibutuhkan di sini.

Membangun Menu: Submenu

Sistem submenu mengambil sedikit lebih banyak pekerjaan, berkat kompleksitas internalnya. Tiga entri pertama, Jarak, Durasi dan Langkah-langkah, secara teknis terdiri dari sub-sub-menu, masing-masing memungkinkan navigasi nilai multi-digit serta setiap karakter individu.

Hal ini tercakup dengan membuat setiap entri submenu sebagai sistem pos yang ditukar dengan haknya sendiri. Meskipun ini masih sangat jauh, ini adalah metode yang sederhana dan konsisten untuk memungkinkan navigasi tingkat rendah seperti itu. Karena saya benar-benar baru mengetahui submenu Jarak dan menyalinnya untuk submenu lainnya, inilah pandangannya.

1
else {    // i.e. "else if currentMenuLevel = 1"

2
    if (currentMenuItem == 0) { //01 DISTANCE

3
4
      switch (btnVal) {
5
      case btnUp:
6
        {
7
          currentChar = currentDistance[currentCursorPos];
8
          adjustDigit(currentChar, 1);
9
          currentDistance[currentCursorPos] = currentChar;
10
          break;
11
        }
12
13
      case btnDn:
14
        {
15
          currentChar = currentDistance[currentCursorPos];
16
          adjustDigit(currentChar, 0);
17
          currentDistance[currentCursorPos] = currentChar;
18
          break;
19
        }
20
21
      case btnL:
22
        {
23
          if (currentCursorPos == 0) break;      //can't go left from here

24
          else currentCursorPos--;
25
          break;
26
        }
27
28
      case btnR:
29
        {
30
          if (currentCursorPos == 3) break;      //can't go left from here

31
          else currentCursorPos++;
32
          break;
33
        }
34
35
      case btnSel:
36
        {
37
          parseArrayDistance();
38
          currentMenuLevel--;
39
        }
40
      }    //end switch

41
    }      //end DISTANCE

Kiri dan kanan pada dasarnya sama dengan menu tingkat atas, hanya bergerak maju mundur sepanjang nomor dengan cara yang sama, dengan memiliki nomor sebenarnya menjadi satu set angka dalam array int dan lokasi saat ini disimpan dalam int yang disebut currentCursorPos yang memungkinkan berkedip seperti yang terlihat pada modul penyegaran layar di atas.

Mencetak array ini di sepanjang baris LCD bawah adalah untuk apa loop untuk di bagian penyegaran layar; i dari 0 hingga 3, kolom LCD dari 0 hingga 3, currentDistance [] dari 0 hingga 3.

1
int adjustDigit(int x, int dir){      //digit adjust function

2
  if (dir == 0 && x > 0) x--;         //subtract from digit on btnDn

3
  if (dir == 1 && x < 9) x++;         // add to digit on btnUp

4
  lcd.setCursor(currentCursorPos, 1);
5
  lcd.print(x);
6
  currentChar = x;
7
  return currentChar;                 //return new digit

8
}

Peningkatan dan penurunan jumlah dicapai dengan menyimpan digit saat ini di variabel currentChar, yang kemudian diteruskan ke fungsi adjustDigit () bersama dengan nilai boolean yang menunjukkan arah; untuk menambah atau mengurangi motor.

Ini hanya menyesuaikan digit sesuai dengan nilai boolean dan menyimpan hasilnya, di mana aliran kembali ke loop utama, di mana nilai currentChar disimpan kembali ke posisi yang benar dari array current.distance [] yang aktif dan digit yang baru disesuaikan dicetak di layar menyegarkan.

Parsing Nilai Tampilan Array

Ketika Pilih dipukul dari salah satu submenu nomor array, itu akan memicu fungsi parsing yang relevan- dalam hal ini parseArrayDistance (). Anda perlu menguraikan larik, digunakan untuk menampilkan dan mengedit dengan mudah, menjadi bilangan bulat yang berguna untuk perhitungan gerak yang sebenarnya. Saya memilih untuk melakukan ini sekarang daripada di Go! untuk membuat UX merasa cepat.

1
int adjustDigit(int x, int dir){      //digit adjust function

2
  if (dir == 0 && x > 0) x--;         //subtract from digit on btnDn

3
  if (dir == 1 && x < 9) x++;         // add to digit on btnUp

4
  lcd.setCursor(currentCursorPos, 1);
5
  lcd.print(x);
6
  currentChar = x;
7
  return currentChar;                 //return new digit

8
}

Saya datang dengan fungsi ini dari satu komentar kelulusan berguna yang saya temukan setelah melelahkan Google mencari fungsi array-to-int standar, datang kosong, dan menyingkirkan kekacauan fungsi array-to-char-to-int yang solusi yang tidak efektif. Kelihatannya cukup pendek dan ringan mengingat itu secara harfiah didasarkan pada pondasi matematika desimal, tetapi jika anda tahu metode yang lebih baik, saya semua telinga.

Kontrol Gerakan dan Pemicu Kamera

Semua nilai ditetapkan dan Anda menekan Go! Apa yang terjadi selanjutnya? Anda perlu menghitung dengan tepat apa yang seharusnya diberikan oleh angka untuk melakukan gerakan terakhir. Bagian ini berfungsi, tetapi masih dalam proses; Saya merasa perlu ada lebih banyak pilihan untuk berbagai jenis gerakan.

1
int motionControl() {
2
  totalMotorSteps = currentDistanceInt * 5; //calculate total steps (0.2mm = 20-tooth gear on 2mm pitch belt; 40mm per rev, 200 steps per rev, ergo 1/5th mm per step)

3
  pulseDelay = (1000L * (currentDurationInt - (currentStepsInt * shutterDuration))) / totalMotorSteps; //how long to pause in ms between STP pulses to the motor driver

4
  intervalDistance = totalMotorSteps / currentStepsInt;

Apa yang terjadi dalam fungsi ini cukup jelas dari komentar, saya kira. Saya telah memasang shutterDuration 2 detik dalam perangkat lunak, terutama untuk menjaga pengujian cukup cepat. Jika anda memotret di malam hari, pada ISO yang lebih rendah, ini mungkin perlu lebih seperti 25-35 detik, tergantung pada kecepatan rana anda.

PulseDelay dikalikan dengan 1000 pada akhirnya untuk mengkonversi dari detik ke milidetik, tentu saja. L untuk mengubah int konstan ke panjang lebih saya berdosa di sisi hati-hati daripada benar-benar diperlukan. Karena sketsa yang relatif kecil, saya tidak terlalu khawatir tentang penggunaan memori variabel.

Perhitungan ini mengasumsikan bahwa loop itu sendiri membutuhkan jumlah waktu yang dapat diabaikan untuk berjalan dibandingkan dengan waktu pulseDelay, yang, setelah saya mengambil polling tombol, tampaknya benar.

1
//once per overall run

2
  if (travelDir == 0) digitalWrite(dir, LOW);
3
  else if (travelDir == 1) digitalWrite(dir, HIGH);
4
  //Serial.begin(9600);

5
  //Serial.println(pulseDelay);

6
7
  //step loop

8
  do {
9
    digitalWrite(stp, HIGH); //fire motor driver step

10
    delay(pulseDelay);
11
    digitalWrite(stp, LOW); //reset driver

12
    //btnVal = readLcdButtons(); //check there's no stoppage - this takes too long and significantly slows motor; use reset for stop!

13
    currentStep++;
14
15
    //at end of each step

16
    if (currentStep % intervalDistance == 0) {    //if current number of motor steps is divisible by the number of motor steps in a camera step, fire the camera

17
      digitalWrite(trig, HIGH); //trigger camera shutter

18
      delay(80);
19
      digitalWrite(trig, LOW);    //reset trigger pin

20
      delay((shutterDuration * 1000)-80); //delay needs changing to timer so stop button can be polled

21
    }
22
23
  }
24
  while (currentStep < totalMotorSteps);
25
26
} //end motion control

Terakhir, perhatikan nilai currentSteps yang ditetapkan pada 1. Saya belum membuat fungsi pengecekan kesalahan untuk ini, tetapi akal sehat sederhana mengatakan stepSize menjadi tidak terbatas jika currentStepsInt == 0, jadi sebaiknya menyimpannya jika gerakan berkelanjutan diinginkan. Saya menambahkan entri perbaikan untuk ini sudah.

Menjalankan Produk Akhir

Untuk sesuatu yang berjalan pada kode yang ditulis kurang lebih dari awal dalam dua hari dan bug diperbaiki lebih dari dua, itu berfungsi seperti mimpi! Buktinya ada di pudding. Apakah itu benar-benar mendapatkan rekaman timelapse berharga, dan apakah unit kontrol benar-benar bekerja dengan baik di lapangan?

Dalam tes saya, jawabannya tampaknya merupakan jawaban yang tulus. Di bawah ini adalah timelapse berdurasi 650 jam, tes pertama. Slider juga menyelesaikan 9 jam 720 frame test dengan sempurna, tapi sayangnya baterai kamera tidak bekerja dengan baik setelah 2 jam ... yang tidak saya temukan sampai tanda 8.5 jam, secara alami.

Jika saya mengatur waktu dan langkah dengan tepat, gerakan dapat terus menerus untuk gerakan dolly yang lambat dalam video aksi langsung, meskipun ujung dendeng perlu diedit atau dipendekkan.

Suara mungkin menjadi masalah kecuali stepper anda sangat senyap, tetapi untuk menambahkan nilai produksi ke rekaman sendiri, itu adalah pilihan.

Perbaikan

Seperti apa pun, ada kemungkinan perbaikan yang harus dilakukan. Saya telah mencantumkan ini di bagian atas file .ino, meskipun diakui tanpa kepedulian khusus atas kelayakan atau diperintahkan oleh jenis kepentingan apa pun.

Beberapa dari ini saya anggap memperbaiki sebelum merilis tutorial ini dengan v0.2, tapi saya merasa seperti mereka dalam diri mereka sendiri adalah pengalaman belajar untuk melihat dalam hal membongkar secara mental kegunaan suatu program.

1
 IMPROVEMENTS AND CONSIDERATIONS TOWARDS V1.0:
2
 1) Efficiency of submenu button response code for first three menu headers
3
 2) Use of bulb shutter time as an extra menu option, passed to shutterDuration int
4
 3) shutter duration should be timed pause, not delay() - can't poll stop button!
5
 4) Use EEPROM library functions to save quantities, can thus simplify the motion control section and use Reset as "stop"
6
 5) Remove switch from "Go" submenu, replace with more appropriate logic statement
7
 6) Would it be better to time camera steps rather than total travel? "duration" being more like 15 sec or 2 min than 30 min or 4hrs?
8
 7) Any const ints that would be better as #define or ints better as boolean? Hardly running against the limits of SRAM space at 8kB, though.
9
 8) Tweening/easing for acceleration curves, particularly for video use
10
 9) Error check for zero step size, or simply add one to intervalDistance if value is zero before calculations- other end of Distance is still 1 step
11
 10) Would sub-16ms delay()s be better as delayMicroseconds()? How much do interrupts throw off timing?
12
 11) Use of sleep on A4988 to reduce power consumption in the field?
13
 12) Error check for currentDurationInt <= currentStepsInt*shutterDuration, allowing no time for movement or even negative pulseDelay!
14
 */

Ini hanyalah perbaikan yang saya pikir sejauh ini, dalam upaya untuk membimbing basis kode dari v0.2 yang belum sempurna tetapi fungsional menuju rilis v1.0 yang lebih optimal dan lebih mampu. Anda mungkin memperhatikan lebih banyak. Jangan ragu untuk meninggalkan mereka di komentar di bawah atau di GitHub.

Membungkus

Jika Anda telah mengikuti dari awal hingga akhir, termasuk bagian Photography Tuts + dari build, anda sekarang adalah pemilik bangga dari slider kamera bermotor berkualitas tinggi yang dapat menghasilkan rekaman timelapse dan gerakan dolly halus. Jika anda menggunakan kode untuk beberapa proyek lain, saya ingin melihatnya.

Dalam tutorial ini, saya telah melihat berbagai bentuk kontrol aliran berbasis loop, menciptakan GUI yang belum sempurna dan memperbarui LCD berdasarkan input pengguna. Saya juga melihat secara bersamaan mengendalikan beberapa perangkat mekanis eksternal melalui papan breakout.

Anda telah melihat aliran dan kemudahan pemrograman kode modular, serta melihat ide untuk cara meningkatkan kode yang fungsional, tetapi tidak dioptimalkan, baik dari sudut pandang efisiensi UX dan prosesor. Alat-alat ini akan melayani anda dengan baik untuk berbagai proyek komunikasi dan interaksi di masa depan.

Silakan tinggalkan pertanyaan atau komentar di bawah ini!

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.