Operácie

Ovladanie krokoveho motora joystickom + uvod displej: Rozdiel medzi revíziami

Z SensorWiki

(Algoritmus a program)
(Analýza a opis riešenia)
Riadok 216: Riadok 216:
  
 
#endif /* MAIN_H_ */
 
#endif /* MAIN_H_ */
</source></tab>
 
 
 
 
 
</source></tab>
 
<tab name="lcd.h"><source lang="c++">
 
 
#ifndef LCD_H_
 
#define LCD_H_
 
 
void LCD_Init(int);
 
void sendHalfByte(unsigned char);
 
void sendByte(unsigned char, unsigned char);
 
void LCD_setPosition(unsigned char, unsigned char);
 
void LCD_sendString(char[]);
 
void LCD_clear(void);
 
void LCD_BackLight(unsigned char);
 
 
#endif /* LCD_H_ */
 
 
</source></tab>
 
 
 
 
</source></tab>
 
<tab name="lcd.c"><source lang="c++">
 
 
 
#include "main.h"
 
 
 
unsigned char portlcd = 0;
 
 
void LCD_Init(int X) {
 
sendHalfByte(0b00000011);
 
_delay_ms(5);
 
sendHalfByte(0b00000011);
 
_delay_us(100);
 
sendHalfByte(0b00000011);
 
_delay_ms(1);
 
sendHalfByte(0b00000010);
 
_delay_ms(1);
 
sendByte(0b00101000, 0); // Data 4bit, Line 2, Font 5x8
 
_delay_ms(1);
 
sendByte(X, 0); //Display ON, Blink OFF  CUrsor ON/OFF vramci premennej
 
_delay_ms(1);
 
 
TWI_TransmitByAddr(portlcd |= 0x08, 0x4E); //BackLight ON
 
 
TWI_TransmitByAddr(portlcd &= ~0x02, 0x4E); //LCD Write ON
 
}
 
 
void LCD_BackLight(unsigned char mode) {
 
switch(mode) {
 
case 0:
 
TWI_TransmitByAddr(portlcd &= ~0x08, 0x4E); //BackLight OFF
 
break;
 
case 1:
 
TWI_TransmitByAddr(portlcd |= 0x08, 0x4E); //BackLight ON
 
break;
 
}
 
}
 
 
void sendHalfByte(unsigned char c) {
 
c <<= 4;
 
 
TWI_TransmitByAddr(portlcd |= 0x04, 0x4E); // Enable E
 
_delay_us(50);
 
 
TWI_TransmitByAddr(portlcd | c, 0x4E);
 
 
TWI_TransmitByAddr(portlcd &= ~0x04, 0x4E); // Disable E
 
_delay_us(50);
 
 
}
 
 
void sendByte(unsigned char c, unsigned char mode) {
 
if(mode == 0) TWI_TransmitByAddr(portlcd &= ~0x01, 0x4E);
 
else TWI_TransmitByAddr(portlcd |= 0x01, 0x4E);
 
unsigned char hc = 0;
 
hc = c >> 4;
 
sendHalfByte(hc);
 
sendHalfByte(c);
 
}
 
 
void LCD_sendString(char s[]) {
 
char n;
 
for(n=0; s[n]!='\0'; n++)
 
sendByte(s[n], 1);
 
}
 
 
void LCD_setPosition(unsigned char x, unsigned char y) {
 
switch(y) {
 
case 0:
 
sendByte(x | 0x80, 0);
 
break;
 
case 1:
 
sendByte((0x40+ x) | 0x80, 0);
 
break;
 
case 2:
 
sendByte((0x10+ x) | 0x80, 0);
 
break;
 
case 3:
 
sendByte((0x50+ x) | 0x80, 0);
 
break;
 
}
 
}
 
 
void LCD_clear(void) {
 
sendByte(0x01, 0);
 
_delay_ms(5);
 
}
 
 
</source></tab>
 
 
 
 
</source></tab>
 
<tab name="adc.h"><source lang="c++">
 
 
#include <avr/io.h>
 
 
#ifndef ADC_H_
 
#define ADC_H_
 
 
 
 
void adc_init(void);                                  // A/D converter initialization
 
 
unsigned int adc_read(char a_pin);
 
 
#endif /* ADC_H_ */
 
 
</source></tab>
 
 
 
</source></tab>
 
<tab name="adc.c"><source lang="c++">
 
 
#include "main.h"
 
 
void adc_init(void){
 
ADMUX = (1<<REFS0);
 
ADCSRA = (1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);
 
}
 
 
unsigned int adc_read(char a_pin){
 
a_pin &= 0x07;
 
ADMUX = (ADMUX & 0xF8)|a_pin;
 
ADCSRA |= (1<<ADSC);
 
while(ADCSRA & (1<<ADSC));
 
 
return(ADC);
 
}
 
 
</source></tab>
 
 
 
 
</source></tab>
 
<tab name="twi.h"><source lang="c++">
 
 
#ifndef TWI_H_
 
#define TWI_H_
 
 
void TWI_Start(void);
 
void TWI_Init(void);
 
void TWI_Stop(void);
 
void TWI_Transmit(unsigned char);
 
void TWI_TransmitByAddr(unsigned char, unsigned char);
 
 
#endif /* TWI_H_ */
 
 
</source></tab>
 
 
 
 
</source></tab>
 
<tab name="twi.c"><source lang="c++">
 
 
#include "main.h"
 
 
void TWI_Init(void) {
 
 
TWBR = 0x48;
 
}
 
 
void TWI_Start(void) {
 
TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
 
while(!(TWCR & (1<<TWINT)));
 
}
 
 
void TWI_Transmit(unsigned char data) {
 
TWDR = data;
 
TWCR = (1<<TWINT) | (1<<TWEN);
 
while(!(TWCR & (1<<TWINT)));
 
}
 
 
void TWI_TransmitByAddr(unsigned char data, unsigned char addr) {
 
TWI_Start();
 
TWI_Transmit(addr);
 
TWI_Transmit(data);
 
TWI_Stop();
 
}
 
 
void TWI_Stop(void) {
 
TWCR = (1<<TWINT) | (1<<TWSTO) | (1<<TWEN);
 
}
 
 
 
</source></tab>
 
</source></tab>
 
</tabs>
 
</tabs>

Verzia zo dňa a času 16:36, 11. jún 2024

Záverečný projekt predmetu MIPS / LS2023 - Matej Ledecky

Zadanie

  • 1. Preštudovanie datasheetov k daným komponentom
  1. Joystick
  2. LCD/I2C
  3. Krokový motor + driver
  • 2.Návrh zapojenia a funkčnosti komponentov
  • 3. Zapojenie
  • 4. Návrh programového riešenia
  1. Čítanie hodnôt z joysticku a vhodná interpretácia pre ďalšie použitie
  2. Pohyb krokového motora v oboch smeroch
  3. Rýchlosť krokového motora
  4. Prepojenie joystick - motor
    1. Ovládanie joystickom smer/rychlosť otáčania
  5. Úvodná obrazovka
    1. Výpis privítania a čo robí daný projekt na LCD
  6. Výpis smeru otáčania na LCD
  • 5. Otestovanie funkčnosti (videodokumentácia)


Hardware:

  • 1.Arduino uno R3
Arduino UNO R3


  • 2.Joystick
Joystick
Schéma zapojenia


  • 3.LED display 16×2 I2C
LCD displej
Schéma zapojenia



  • 4.Krokový motor 28BYJ-48 modul ULN2003
Krokovy motor + driver
Schéma zapojenia



Schéma zapojenia zariadenia:


Schéma zapojenia zariadenia




Literatúra:


Analýza a opis riešenia

  • 1.Najprv som pripojil joystick a vyhotovil jeho programové riešenie. Joystick je súčiastka, ktorá funguje štandardne na báze potenciometra, variabilného rezistora, ktorý mení odpor pri zmene polohy. Tento konkrétny joystick má dve osi pohybu (x a y) a tlačidlo. Na toto zariadenie použijeme jednu os pohybu, ktorú pripojíme na A/D prevodník s použitím knižnice, ktorú sme používali na cvičeniach.
  • 2.Ďalej som zapojil krokový motor spolu s driverom a vyhotovil programový systém, pri ktorom je možné motorom otáčať a aj meniť jeho rýchlosť. Krokový motor 28BYJ-48 s modulom ULN2003 funguje na princípe rozdelenia celého otáčania na kroky. Každý krok zodpovedá určitému uhlu otáčania. ULN2003 je ovládač, ktorý prijíma signály z mikrokontroléra a riadi cievky motora. Postupným napájaním cievok v správnom poradí sa motor pohybuje o jeden krok. Tento spôsob umožňuje presné riadenie pozície a rýchlosti motora. Jednoducho povedané, motor sa otáča v malých krokoch riadených elektrickými impulzmi z ovládača ULN2003.
  • 3.Pokračoval som prepojením týchto dvoch funkcií s výsledným cieľom, aby som vedel podľa smeru otočenia páčky (buď vľavo alebo vpravo) riadiť smer krokového motora a intenzitou ohybu v danom smere riadiť rýchlosť. Smer je riešený podľa výstupných parametrov systému: pri hodnotách v nižšej polovici možných výstupných hodnôt je jeden smer a pri vyššej druhý, pričom program ráta aj s takzvaným mŕtvym stredom (stav, kedy sa nič nedeje). Funkcia rýchlosti vychádza z úpravy delayu medzi jednotlivými krokmi motora, pričom hodnota pre úpravu vychádza z hodnoty výstupu joysticka.
  • 4.V poslednom programovom kroku som vyhotovil jednoduchú úvodnú obrazovku (info k zariadeniu vid video) spolu s výpisom smeru otáčania. Realizácia spočívala v pripojení LCD LED displeja 16×2 s I2C modulom, s ktorým sa pracuje podobne ako na cvičení, s rozdielom, že tu sa používa aj I2C, s ktorým sme sa stretli tiež na cvičení.
  • 5.Na záver som všetko odskúšal a po overení funkčnosti vyhotovil jednoduchú inštalačnú dosku pre dané zariadenie, ktorá bola z dreva a mosadzných úchytov, a vytvorila celistvé zariadenie s jednoduchým ovládaním.

Algoritmus a program

#include "main.h"		// vlozenie potrebnych includeov prepojeni	

#define X_PIN 0			//definovanie pinov joysticku
#define Y_PIN 1

void delay(int delay)		// klasicky delay
{
	for (int i=1; i<=delay; i++)
	_delay_ms(1);
}

void delayus(int delay)			//us delay pre pozitie v rotacii ako regulacia rychlosti
{
	for (int i=1; i<=delay; i++)
	_delay_us(1);
}

void left(char Pole[],int Speed){		//tocenie doprava
	 for (int L=0;L<10;L++)
	for(int i = 0; i < 4; i++){
		PORTD = Pole[i];
		delayus(4250 - Speed*20);
	}
		PORTD = 0b00000000;
	 
}

void right(char Pole[], int Speed){		// tocenie dolava
	 for (int L=0;L<10;L++)
	for(int i = 3; i >= 0; i--){
		PORTD = Pole[i];
		delayus(4000 - Speed*20);
	}
		PORTD = 0b00000000;
	 
}


int main(void)
{
	
	MCUCR &= ~(1<<PUD);

	DDRD |= 0b00111100;		//paramatre pre otacanie
	char Pole[] = {0b00100000, 0b00010000, 0b00001000, 0b00000100};
 
	int Speed = 0;

	unsigned int Valuex;	// premenne pre nacitanie s AD prevodnika
	unsigned int Valuey;
	unsigned int Value;
	
	int x = 0b00001110; // premenna pre mod LCD cursor on/OFF
	int y = 0b00001100;
	
	
	char *num;

	TWI_Init();			//inicializacie TWI LCD ADC + uvodne texty
	delay(500);
	
	LCD_Init(y);
	delay(500);
	LCD_clear();
	delay(500);
	LCD_sendString("Vitajte");		
	delay(2000);
	LCD_clear();
	delay(500);
	
	LCD_sendString("Riadenie Motora ");
	LCD_setPosition(0,1);
	LCD_sendString("Joystickom");
	delay(2000);
	LCD_clear();
	delay(500);

	LCD_sendString("Smer otacania");
	LCD_setPosition(0,1);
	delay(500);
	
	adc_init();
	delay(500);
	
	while(1){

		Valuex = adc_read(X_PIN)/4;		//Citanie s AD do valuex
		if(Valuex > 125){				//pobyb packy po osi x dolava
			Speed=Valuex-123;			//vypocet konstatny rychlosti
			left(Pole,Speed);			// rotacia dolava
			LCD_setPosition(0,1);		// pozicia kurzora LCD
			LCD_sendString("<--");		// vypis na LCD
			
		}
		else if(Valuex < 124){			//to iste len do druhej strany s mensimi upravami kvoli rozdielnym hodnotam s AD
			Speed=127-Valuex;
			right(Pole, Speed);
			LCD_setPosition(0,1);
			LCD_sendString("-->");
		}
		else{
			LCD_setPosition(0,1);		// KED nic
		    LCD_sendString("<->");
		} 
	/*	num = (char *)malloc(snprintf(NULL, 0, "%d", o) + 1);
		LCD_sendString(num);
		free(num); */
	

	}
	return(0);
	
}
#ifndef MAIN_H_
#define MAIN_H_

#define BAUD 9600
#define F_CPU 16000000UL

#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdio.h>
#include <util/delay.h>

#include "adc.h"
#include "twi.h"
#include "lcd.h"

#endif /* MAIN_H_ */

Ukážka zariadenia

Video s prezentáciou funkcie