regulátor otáček ( kroků ) krokového motoru

Pidrman
Příspěvky: 53
Registrován: 19. 1. 2015, 6:24

9. 9. 2015, 7:26

Tak jsem asi lama :-)

Nevím jak to zkrátit, nerad bych narušil ten program nějakou mezetru nebo smazáním mezery v programu.
Uživatelský avatar
Thomeeque
Příspěvky: 8950
Registrován: 30. 1. 2012, 10:20
Bydliště: Mimo ČR

9. 9. 2015, 9:57

Teď už nijak, post se dá upravit jen pár hodin po odeslání. Jinak jak jsem psal, uzavřenim do tagu CODE:
Pidrman píše:Co se týče programu, tak tady je..... jen jsem upravil podle rad typ hodnoty u tick_count, změnil jsem původní hodnotu int tick_count; na unsigned long tick_count; :

Kód: Vybrat vše

#include <LiquidCrystal.h>
#include <TimerOne.h>

// buttons code 
#define btnRIGHT  0
#define btnUP     1
#define btnDOWN   2
#define btnLEFT   3
#define btnSELECT 4
#define btnNONE   5

// directions
#define FORWARD   HIGH
#define BACKWARD  LOW

// debounce time (milliseconds)
#define DEBOUNCE_TIME  200

// PINs for Pololu controller
#define PIN_STEP  2
#define PIN_DIR   3

// lookup table speed - ticks (interrupts)
const int speed_ticks[] = {-1, 600, 300, 200, 150, 120, 100, 86, 75, 67, 60, 55, 50, 46, 43};

// global variables
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

int actual_speed;
int actual_direction;

int ticks;
unsigned long tick_count;

int button;
boolean debounce;
int previous_time;

// custom LCD square symbol for progress bar
byte square_symbol[8] = {
  B11111,
  B11111,
  B11111,
  B11111,
  B11111,
  B11111,
  B11111,
};

// string constants
char forward_arrow[] = "-->";
char backward_arrow[] = "<--";

void setup() {

  // init the timer1, interrupt every 0.1ms
  Timer1.initialize(100);
  Timer1.attachInterrupt(timerIsr);
  
  // init LCD and custom symbol  
  lcd.begin(16, 2);
  lcd.setCursor(0,0);
  lcd.createChar(0, square_symbol);
  
  // pins direction
  pinMode(PIN_STEP, OUTPUT);
  pinMode(PIN_DIR, OUTPUT);
  
  // initial values
  actual_speed = 0;
  actual_direction = FORWARD;
  tick_count = 0;
  ticks = -1;
  debounce = false;

  digitalWrite(PIN_DIR, actual_direction);  
  updateLCD();
}
  
void loop() {
  
  // check if debounce active
  if(debounce) {
    button = btnNONE;
    if(millis() > previous_time + DEBOUNCE_TIME) debounce = false;
  } else button = read_buttons();
  
  // if a button is pressed, start debounce time
  if(button != btnNONE) {
    
    previous_time = millis();
    debounce = true;  
  }
    
  // check which button was pressed
  switch(button) {
    
    case btnUP:
      increase_speed();
      break;
    case btnDOWN:
      decrease_speed();
      break;
    case btnLEFT:
      change_direction(BACKWARD);
      break;
    case btnRIGHT:
      change_direction(FORWARD);
      break;
    case btnSELECT:
      emergency_stop();
      break;
  }
  
  // finally update the LCD
  updateLCD();
}

// increase speed if it's below the max (70)
void increase_speed() {
  
  if(actual_speed < 70) {
    actual_speed += 1;
    tick_count = 0;
    ticks = speed_ticks[actual_speed / 5];
  }
}

// decrease speed if it's above the min (0)
void decrease_speed() {
  
  if(actual_speed > 0) {
    actual_speed -= 1;
    tick_count = 0;
    ticks = speed_ticks[actual_speed / 5];
  }
}

// change direction if needed
void change_direction(int new_direction) {
  
  if(actual_direction != new_direction) {
    actual_direction = new_direction;
    digitalWrite(PIN_DIR, actual_direction);
  }
}

// emergency stop: speed 0
void emergency_stop() {
  actual_speed = 0;
  tick_count = 0;
  ticks = speed_ticks[actual_speed / 5];
}

// update LCD
void updateLCD() {
  
  // print first line:
  // Speed: xxxRPM -> (or <-)
  lcd.setCursor(0,0);
  lcd.print("SPEED: ");
  lcd.print(actual_speed);
  lcd.print("RPM ");

  lcd.setCursor(13,0);
  if(actual_direction == FORWARD) lcd.print(forward_arrow);
  else lcd.print(backward_arrow);
  
  // print second line:
  // progress bar [#####         ]
  // 15 speed steps: 0 - 5 - 10 - ... - 70
  lcd.setCursor(0,1);
  lcd.print("[");
  
  for(int i = 1; i <= 14; i++) {
    
    if(actual_speed > (5 * i) - 1) lcd.write(byte(0));
    else lcd.print(" ");
  }
  
  lcd.print("]");
}

// timer1 interrupt function
void timerIsr() {

  if(actual_speed == 0) return;
  
  tick_count++;
  
  if(tick_count == ticks) {  
    
    // make a step
    digitalWrite(PIN_STEP, HIGH);
    digitalWrite(PIN_STEP, LOW);
    
    tick_count = 0;
  }
}

// read buttons connected to a single analog pin
int read_buttons() {
  
  int adc_key_in = analogRead(0);
 
  if (adc_key_in > 1000) return btnNONE;
  if (adc_key_in < 50)   return btnRIGHT;  
  if (adc_key_in < 195)  return btnUP; 
  if (adc_key_in < 380)  return btnDOWN; 
  if (adc_key_in < 555)  return btnLEFT; 
  if (adc_key_in < 790)  return btnSELECT;   
}
Citovanej kód to nijak nemodifikuje, jen ho to vhodně nastyluje. S formátovánim na githubu, pastebinu atp. se to nedá srovnat (takže pokud to máš tam, je to asi nejlepší možnost), ale je to imho lepší, než to prásknout do příspěvku jen tak.
Pidrman píše:Přípona není povolena.

Jak to mam tady sem vložit ?
Standardní trik je přidat ke jménu souboru ještě nějakou podporovanou příponu (tipuju, že třeba .txt by prošla) a upozornit na to.

T.
mimooborová naplavenina • kolowratský zázrak™ • NPS • GCU • HirthCalc • ncDP.ino
Pidrman
Příspěvky: 53
Registrován: 19. 1. 2015, 6:24

9. 9. 2015, 10:54

Ok a díky, už jsem moudřejší :-)
Uživatelský avatar
Thomeeque
Příspěvky: 8950
Registrován: 30. 1. 2012, 10:20
Bydliště: Mimo ČR

11. 9. 2015, 3:58

Pidrman (SZ) píše:Ahoj

Pomohl by jsi mi tedy s tím programem na to arduino prosím ? Já z toho fakt nejsem :-(

Předem díky Honza
Ahoj, já si s arduinem nikdy nehrál. Nicméně program jsem si přečet a celkem ho i chápu. Pár věcí bych dělal jinak (to násobení-dělení 5ti kolem actual_speed např.), ale očividný důvod pro zamrzání tam nevidim. Jen tak baj voko tipuju, jestli by to nemohl být konflikt mezi obsluhou Timer1 a obsluhou LCD, ten Timer se volá s poměrně velkou frekvencí a kolem LCD se toho možná bude dít taky dost. Zkusil bych to o LCD obsluhu pro začátek zcela očesat. Ale nevim (autorovi to zjevně funguje - používáte stejný HW?), snad se ozve někdo znalejší.

T.

Btw. smysl změny tick_count z int na unsigned long moc nechápu (pokud ticks a speed_ticks zůstávájí int), kde to bylo doporučeno?
mimooborová naplavenina • kolowratský zázrak™ • NPS • GCU • HirthCalc • ncDP.ino
Mex
Příspěvky: 10287
Registrován: 6. 2. 2014, 10:29

11. 9. 2015, 4:58

Já teda na používání knihovem moc nejsem. Ale docela se mi zalíbila (zatím jen teoreticky, ještě jsem nezkoušel) knihovna AccelStep.
S tou by se ta tvoje aplikace měla dát napsat na pár řádků (myslím to focení mimozemšťanů).
teensy
Příspěvky: 8
Registrován: 29. 6. 2014, 7:19

17. 9. 2015, 9:06

Ahoj, program se nekousne, jen přestane generovat signál STEP kvůli striktní podmínce tick_count == ticks v obsluze přerušení timmeru. Správně by mělo být tick_count >= ticks. Protože pokud se program jednou dostane do situace, kdy je tick_count větší než ticks, bude se tick_count už jen zvětšovat a vzdalovat se tak od možnosti podmínku splnit

// timer1 interrupt function
void timerIsr()
{
...
tick_count++;

if(tick_count == ticks)
{
// make a step
digitalWrite(PIN_STEP, HIGH);
digitalWrite(PIN_STEP, LOW);
tick_count = 0;
}
}

Pozn: tiscks není konstanta. Řekněme že tick_count se už pomalu blíží hodnotě ticks. Procesor opustí obsluhu interruptu a vrátí se k vykonávání main loop, kde proměnnou ticks skokově změní na hodnotu menší než tick_count. Poté nastane další přerušení timeru a jsme v situaci, kdy je tick_count ostře větší než ticks. A v tomto blbém stavu program setrvá až do doby než typ long přeteče svůj rozsah.
teensy
Příspěvky: 8
Registrován: 29. 6. 2014, 7:19

17. 9. 2015, 9:37

a také si prověř, zda doba trvání pulsu STEP, není pro tvůj driver příliš krátká. Tahle sekvence generuje puls v řádu mikrosekund a driver by na ni nemusel bezpečně reagovat.

// make a step
digitalWrite(PIN_STEP, HIGH);
digitalWrite(PIN_STEP, LOW);
Uživatelský avatar
Thomeeque
Příspěvky: 8950
Registrován: 30. 1. 2012, 10:20
Bydliště: Mimo ČR

17. 9. 2015, 9:50

Jo, to jsem si taky řikal.

Ale s těmi ticks nevim, všude, kde mění hodnotu ticks, zároveň nastavuje tick_count = 0.. ale zkusit to může.
mimooborová naplavenina • kolowratský zázrak™ • NPS • GCU • HirthCalc • ncDP.ino
Pidrman
Příspěvky: 53
Registrován: 19. 1. 2015, 6:24

18. 9. 2015, 5:41

Tak problém je vyřešen a úspěšně vše funguje :-)

V příloze je celý kod. akonec zabrala změny typ proměnné z "int" na "unsigned long"

Jinak všem moc a moc děkuji ................ tyhle poslední změny taky zkusím, chci se to naučit, tak si s tím budu pořád hrát :-)


Honza
Přílohy
cntrSpeedDir_uprava.zip
(1.82 KiB) Staženo 181 x
Odpovědět

Zpět na „Krokové motory“