Conveyor Belt Sorting System Using ATmega328P

Automated conveyor system using ATmega328P bare-metal C programming. Features IR detection, PWM speed control, and LCD monitoring.

IntermediateFull instructions provided37
Conveyor Belt Sorting System Using ATmega328P

Things used in this project

Hardware components

ATmega328
Microchip ATmega328
×1
RGB Backlight LCD - 16x2
Adafruit RGB Backlight LCD - 16x2
×1
IR Range Sensor
Digilent IR Range Sensor
×1
Dual H-Bridge motor drivers L298
SparkFun Dual H-Bridge motor drivers L298
×1
DC Motor, 12 V
DC Motor, 12 V
×1
Single Turn Potentiometer- 10k ohms
Single Turn Potentiometer- 10k ohms
×1
Solderless Breadboard Full Size
Solderless Breadboard Full Size
×1
Female/Female Jumper Wires
Female/Female Jumper Wires
×1

Software apps and online services

Proteus 8 Profesional
PlatformIO IDE
PlatformIO IDE
VS Code
Microsoft VS Code

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)
Solder Flux, Soldering
Solder Flux, Soldering

Story

Read more

Schematics

Schematic Wiring In Proteus 8

Code

Main Code using Platform IO

C/C++
#include <Arduino.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdbool.h>

volatile int products_entered = 0;
volatile int products_left = 0;
volatile bool motor_running = false;
volatile uint8_t current_pwm_value = 0;

void lcd_write_port(uint8_t data) {
    PORTB &= ~((1 << PB0) | (1 << PB2) | (1 << PB3) | (1 << PB4) | (1 << PB5));
    PORTC &= ~((1 << PC3) | (1 << PC4) | (1 << PC5));

    if (data & 0x01) PORTB |= (1 << PB0); // D0
    if (data & 0x02) PORTB |= (1 << PB2); // D1
    if (data & 0x04) PORTB |= (1 << PB3); // D2
    if (data & 0x08) PORTB |= (1 << PB4); // D3
    if (data & 0x10) PORTB |= (1 << PB5); // D4
    if (data & 0x20) PORTC |= (1 << PC3); // D5
    if (data & 0x40) PORTC |= (1 << PC4); // D6
    if (data & 0x80) PORTC |= (1 << PC5); // D7
}

void lcd_command(uint8_t cmd) {
    PORTD &= ~(1 << PD4); // Set RS = 0 
    lcd_write_port(cmd);  
    
    // Pulse Enable
    PORTD |= (1 << PD5); 
    _delay_us(1); 
    PORTD &= ~(1 << PD5); 

    // Clear Display dan Return
    if (cmd == 0x01 || cmd == 0x02) {
        _delay_ms(2);
    } else {
        _delay_us(100);
    }
}

void lcd_data(char data) {
    PORTD |= (1 << PD4);  // Set RS = 1 
    lcd_write_port(data); 
    
    // Pulse Enable
    PORTD |= (1 << PD5); 
    _delay_us(1); 
    PORTD &= ~(1 << PD5); 
    _delay_us(100);
}

void lcd_init() {
    DDRB |= (1 << PB0) | (1 << PB2) | (1 << PB3) | (1 << PB4) | (1 << PB5);
    DDRC |= (1 << PC3) | (1 << PC4) | (1 << PC5);
    DDRD |= (1 << PD4) | (1 << PD5); 
    
    _delay_ms(20); 
    PORTD &= ~(1 << PD4); 

    lcd_command(0x38); 
    _delay_ms(5);
    lcd_command(0x38); 
    _delay_us(15);
    lcd_command(0x38);
    lcd_command(0x0C); 
    lcd_command(0x06); 
    lcd_command(0x01); 
}

void lcd_print(const char* str) {
    while (*str) {
        lcd_data(*str++); 
    }
}

void lcd_print_num(int num) {
    char buffer[6];
    int i = 0;
    if (num == 0) {
        lcd_data('0');
        return;
    }
    while (num > 0) {
        buffer[i++] = (num % 10) + '0';
        num /= 10;
    }
    while (i > 0) {
        lcd_data(buffer[--i]);
    }
}

void lcd_set_cursor(uint8_t col, uint8_t row) {
    uint8_t row_offsets[] = {0x00, 0x40};
    lcd_command(0x80 | (col + row_offsets[row]));
}

void adc_init() {
    ADMUX = (1 << REFS0); 
    ADCSRA = (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); 
}

uint16_t adc_read() {
    ADCSRA |= (1 << ADSC); 
    while (ADCSRA & (1 << ADSC)); 
    return ADC; 
}

void pwm_init() {
    DDRB |= (1 << PB1); // OC1A Output
    TCCR1A = (1 << COM1A1) | (1 << WGM10); // Fast PWM 8-bit
    TCCR1B = (1 << WGM12) | (1 << CS11) | (1 << CS10); // Prescaler 64
}

void motor_init() {
    DDRC |= (1 << PC1) | (1 << PC2); 
}

void interrupt_init() {
    DDRD &= ~((1 << PD2) | (1 << PD3)); 
    PORTD |= (1 << PD2) | (1 << PD3);   
    EICRA = (1 << ISC11) | (1 << ISC01);
    EIMSK = (1 << INT1) | (1 << INT0);  
}

ISR(INT0_vect) {
    products_entered++;
    motor_running = true; 
    
    PORTC |= (1 << PC1);  
    PORTC &= ~(1 << PC2); 
    OCR1A = current_pwm_value;
}

ISR(INT1_vect) {
    products_left++;
    motor_running = false; 
    
    // Matikan motor
    PORTC &= ~(1 << PC1); 
    PORTC &= ~(1 << PC2); 
    OCR1A = 0;
}

void setup() {
    lcd_init();         
    adc_init();         
    pwm_init();         
    motor_init();       
    interrupt_init();   
    sei();              

    lcd_set_cursor(0, 0);
    lcd_print("Project Uas");
    lcd_set_cursor(0, 1);
    lcd_print("Kelompok 2 IVA");
    _delay_ms(100);
    lcd_command(0x01);  
}

void loop() {
    uint16_t pot_value = adc_read();
    current_pwm_value = pot_value >> 2; 

    if (motor_running) {
        PORTC |= (1 << PC1);  
        PORTC &= ~(1 << PC2); 
        OCR1A = current_pwm_value;    
    } else {
        PORTC &= ~(1 << PC1); 
        PORTC &= ~(1 << PC2); 
        OCR1A = 0;            
    }

    uint8_t speed_percent = (current_pwm_value * 100) / 255;
    
    lcd_set_cursor(0, 0);
    lcd_print("Spd:");
    if(speed_percent < 100) lcd_print(" ");
    if(speed_percent < 10) lcd_print(" "); 
    lcd_print_num(speed_percent);
    lcd_print("% St:");
    lcd_print(motor_running ? "RUN " : "STOP");

    lcd_set_cursor(0, 1);
    lcd_print("In:");
    lcd_print_num(products_entered);
    lcd_print(" Out:");
    lcd_print_num(products_left);
    lcd_print("    ");
    
    _delay_ms(15); 
}

Credits

Lor Ino
1 project • 1 follower
Diaz Erlangga Al Farizi
0 projects • 0 followers
14. Jannus Fransiskus Sinaga
0 projects • 0 followers
Arrayan Munzi hipni
0 projects • 0 followers
Gilang Wirakusuma10
0 projects • 0 followers
Alghafari Muhammad Khadafi
0 projects • 0 followers
mulia asih
0 projects • 0 followers

Comments