Professional Documents
Culture Documents
OF TECHNOLOGY
GROUP MEMBERS
The operations of the motor control system follow the sequence below:
1. MCU1 and MCU2 are connected through I2C communication. MCU1 acts as the master
device and sends mode commands, required motor speed and required motor position.
2. MCU1 will have a keypad and an LCD with the user can interact with. A user will be able
to select the mode using the mode_select button (the ‘+’ key on the keypad). The system will
have 2 modes
Mode 1 – Speed control (M-Speed)
Mode 2 – Position control (M-Pos)
Once M-Speed has been selected, the user can then input the required speed in RPM. This
should be displayed on the LCD. Once complete by pressing the Enter button (the ‘ON/C’
key on the keypad). The mode and speed setting is sent to MCU2 via I2C.
LCD Display Sample:
Mode: M-Speed
Speed: _ _ _ RPM
Similarly once M-Pos has been selected the user can then input the number of rotations for
the motor to turn. This should be displayed on the LCD. Once complete by pressing the Enter
button (the ‘ON/C’ key on the keypad). The mode and speed setting is sent to MCU2 via I2C.
LCD Display Sample:
Mode: M-Pos
Pos: _ _ _ REV
3. MCU2 will ensure the motor moves according to the setting required. It should display the
mode, the setting and the current value for speed or position of the motor.
2. 16X2 LCD
LCD stands for Liquid Crystal Display. The 16X2 LCD is an Alphanumeric display.
It consists of a segmented screen of 16 columns and 2 rows, which allows for display
of up to 32 characters to transmit information. They are easy to interface and consume
little power hence are widely used in such systems.
LCD 16x2 is a 16 pin devices which has 8 data pins (D0-D7) and 3 control pins (RS,
RW, EN). The remaining 5 pins are for power supply and backlight for the LCD. The
3 control pins help us configure the LCD in command mode or data mode. They also
help to configure the LCD into read mode or write mode. LCD 16x2 can be used in 4-
bit mode or 8-bit mode depending on requirement of application. In order to use it we
need to send certain commands to the LCD in command mode and once the LCD is
configured according to our need, we can send the required data in read mode.
We shall use the LCD in 4 bit mode which is easier to interface to the Atmega32
3. 4X4 Keypad
b) Keypad Set-up
#include <string.h>
#define KEY_PIN PIND // Keypad input pin
c) ADC Functions
d) Timer Set-Up
/*Timer setup function*/
void timer_setup(){
TIMSK |= (1<<TOIE1); // Activate the timer overflow interrupt
TCCR1B = (1<<CS11)|(1<<CS10); // Set the timer prescalar to 64
TCNT1 = 3036; // Load the countdown value for 500ms
}
e) Interrupt Set-up
/*Interrupt setup function*/
void interrupt_setup(){
DDRB = 0xFF; // Make PORTB as output Port
DDRB &= ~(1<<PB2); // Make INT2 pin as Input
DDRB |= (1<<PB3); // Make OC0 pin as Output
DDRD &= ~(1<<PD2); // Make INT0 pin as Input
DDRD &= ~(1<<PD3); // Make INT0 pin as Input
GICR = (1<<INT2)|(1<<INT1)|(1<<INT0); // Enable INT0, INT2
MCUCR = (1<<ISC00)|(1<<ISC10); // Trigger INT0 on Logic change trigger
MCUCSR = (1<<ISC2);// Trigger INT2 on Rising Edge triggered
sei(); // Enable Global Interrupt */
}
/* Interrupt ISR functions */
ISR(INT0_vect){
cur_encode = PIND & ((1<<PD2)|(1<<PD3));
cur_encode = (cur_encode>>2);
// From the encoder value chart, when Channel A changes logic states we
look
// at the value of the interrupt pins. If they are either 0b 11 or 0b
00,
// the motor is moving CW and we decrease the count
if(cur_encode == 0x03 || cur_encode == 0x00){
count-=1;
}
// If they are either 0b 10 or 0b 01, the motor is moving CCW and we
increase the count
else if(cur_encode == 0x02 || cur_encode == 0x01){
count+=1 ;
}
}
ISR(INT1_vect){
cur_encode = PIND & ((1<<PD2)|(1<<PD3)); // Obtain the reading from the
PIND2 and PIND3
cur_encode = (cur_encode>>2);
// From the encoder value chart, when Channel B changes logic states we
look
// at the value of the interrupt pins. If they are either 0b 01 or 0b
10,
// the motor is moving CW and we decrease the count
if(cur_encode == 0x01 || cur_encode == 0x02){
count-=1;
}
// If they are either 0b 11 or 0b 00, the motor is moving CCW and we
increase the count
else if(cur_encode == 0x03 || cur_encode == 0x00){
count+=1;
}
}
ISR(INT2_vect){
Direction = ~Direction; // Toggle Direction
_delay_ms(50); // Software de-bouncing control delay
}
f) PWM Set-up
/*ISR function: run whenever there is a new key press from the MMC74C922*/
ISR(INT0_vect){
// Read the value from the keypad connected pins
char value = PINB & (0x0F);
unsigned char keycheck = check_Keypad(value);
// If the key pressed is C, send a message to MCU2
if (keycheck == '+'){
mode = ~mode; // Toggle mode
LCD_Clear();
_delay_ms(50); // Software de-bouncing control delay
}else if (keycheck == 'C'){
send_cmd = ~send_cmd;
keycount = 0;
}else if (keycheck == '*'){
PORTA |= (1<<PA7);
_delay_ms(100);
PORTA &= ~(1<<PA7);
}else{
if(keycount < 0){
keycount++;
}else if((keycount>= 0) && (keycount < snd_len)){
send_msg[keycount] = keycheck;
keycount++;
if(keycount == snd_len) keycount = 0;
}
}
}
/*Function to select the mode to display*/
//Passed value from main function is used as switch value
void mode_sel(int case_val){
int buffer;
int count;
switch (case_val)
{
//Position display and sending of values
case 0:
//Display setup
LCD_String_xy(0,0, "Mode:M-Pos");
LCD_String_xy(1,0,"Pos:");
LCD_String(send_msg); //Displays the pressed characters
LCD_String_xy(1,11,"REV");
//Checks if the send_cmd is toggled in order to send
if (send_cmd)
{
buffer = atoi(send_msg); //Conversion of message from
string to integer
//increase the converted value by one
//Send both the converted value and increased value in
order to recognize the mode sent to slave
count = buffer+1;
//For loop for sending both values
for (get = 0;get<2;get++)
{
if (get == 0)
{
SPI_Write(buffer);
} if (get == 0)
{
SPI_Write(count);
}
}
send_cmd = FALSE; //Return send command to initial state
clear_send(send_msg); //clear message buffer
}
break;
case 1:
//Display setup
LCD_String_xy(0,0, "Mode:M-Speed");
LCD_String_xy(1,0,"Speed:");
LCD_String(send_msg); //Displays the pressed characters
LCD_String_xy(1,11,"RPM");
if (send_cmd)
{
buffer = atoi(send_msg); //String to integer conversion
//Send the converted value twice in order to recognize the
mode sent to slave
for (get = 0;get<2;get++)
{
SPI_Write(buffer);
}
send_cmd = FALSE; //Return send command to initial state
clear_send(send_msg); //clear message buffer
}
break;
}
}
int main(void)
{
LCD_Init();
I2C_Slave_Init(Slave_Address);
keypad_Init();
/*Emergency stop pin direction*/
DDRA = 1<<PA7;
/* Replace with your application code */
while (1)
{
#define F_CPU 8000000UL /* Define CPU clock Frequency e.g. here its 8MHz */
#include <avr/io.h> /* Include AVR std. library file */
#include <util/delay.h> /* Include inbuilt defined Delay header file */
#include <stdio.h> /* Include standard I/O header file */
#include <stdlib.h> /* Include string header file */
#include "I2C_LCD_Initialization.h" /* Include LCD header file */
#include "I2C_Slave_Functions.h" /* Include I2C slave header file */
#include "Keypad_Initialization.h"
#define Slave_Address 0x20
int8_t sensor_select = 0;
void pwm_setup(){
/* GPIO setup */
DDRB |= (1<<PB3); // Make OC0 pin as Output
/* PWM setup */
TCCR0 = (1<<WGM00)|(1<<WGM01)|(1<<COM01)|(1<<CS02); // Set Fast PWM with
Fosc/256 Timer0 clock
}
int main(void)
{
LCD_Init();
SPI_Init();
pwm_setup();
interrupt_setup();
timer_setup();
/* Replace with your application code */
while (1)
{
received();
}
Outputs
Mode selection
Real-time Output
The MCU2 was to give real time output as a comparison to the selected settings by
the user. This was for both the Position Mode and Speed mode as illustrated below
Emergency Stop
When the ‘X’ key was presses the emergency stop was supposed to be executed by
MCU2 stopping the motor immediately and displaying “EMERGENCY! STOP!”.
as shown Bellow;
Motor Running
The motor runs as instructed and gives feedback
The primary features of the system include two operational modes: speed control (M-
Speed) and position control (M-Pos). The user interface, consisting of the keypad and
LCD on MCU1, allows users to select the desired mode, input parameters (speed or
position), and initiate the motor control sequence. The I2C communication facilitates
the transmission of mode commands, required motor speed, and position from MCU1
to MCU2.
Upon selecting the speed control mode, users can input the desired speed in RPM,
displayed on the LCD. Similarly, in position control mode, users input the number of
rotations for the motor. MCU2 receives these settings, ensuring the motor moves
accordingly and displays the mode, setting, and current motor value on its LCD.
The system incorporates a safety feature where MCU1 includes an emergency button
('X' key), which, when pressed, triggers an emergency stop on MCU2. The emergency
stop is indicated on MCU2's LCD, and this state can only be reversed by resetting
MCU2 using the microcontroller reset button.
The project demonstrates the effective use of embedded systems, I2C communication,
and mechatronics principles. The combination of user interface elements, motor
control, and safety features showcases the versatility and practicality of the designed
system. The successful implementation of this mechatronic system aligns with the
requirements of various applications, including aerospace, aviation, robotics, and
industrial automation, where precise motor control is paramount. The modular design
allows for further expansion and customization, making it a robust platform for
diverse mechatronic applications.
REFFERENCES
i. EMT 3202 Mechatronics System Programming 2 Notes 1 and Notes 2
ii. Che, A. (2008). PID Control System Implementation in Embedded System for
DC Motor Speed Control.
iii. d’Avella, A., Giese, M., Ivanenko, Y. P., Schack, T., & Flash, T. (2016).
Modularity in Motor Control: From Muscle Synergies to Cognitive Action
Representation. Frontiers Media SA.
iv. M
ishra, B. K., Borah, S., & Hemant Kasturiwale. (2022). Computing and
Communications Engineering in Real-Time Application Development. CRC
Press.