Helping code (manipulating registers) on dual lift motor controller project

ok so i tried to make this project with code that was made from manipulating register instead of using (digitalWrite, digitalRead, AnalogRead, etc.) due to my teachers rules.

so i tried wrote the code for both master and slave (it's using I2C as serial communication that sends data (1-6) from master to slave in order to determine which motor direction will move in slave part), i'm using arduino nano for this project, but i encountered this problem (data that sends from master's part keep sending '0' even though i'm using interrupt service routine (ISR)).

here's the code that i wrote, i hope someone could help me out of this, thanks in advance!

Master's Code:

#include <avr/io.h>
#include <avr/interrupt.h>
#include <Wire.h>

#define SLAVE_ADDRESS 0x04

volatile bool button1Pressed = false;
volatile bool button2Pressed = false;
volatile bool button3Pressed = false;
volatile bool button4Pressed = false;
volatile bool button5Pressed = false;
volatile bool button6Pressed = false;
volatile int data = 0;

long last_time = 0;
long debounce_delay = 100;

ISR(PCINT2_vect) {
  if ((PIND >> 4 & 0b00010000 >> 4) == 1){
    if(millis() - last_time >= debounce_delay){
      button1Pressed = !button1Pressed;
      data = 1;
      last_time = millis();
      }
  }
  else if ((PIND >> 5 & 0b00100000 >> 5) == 1){
    if(millis() - last_time >= debounce_delay){
      button2Pressed = !button2Pressed;
      data = 2;
      last_time = millis();
    }
  }
  else if ((PIND >> 6 & 0b01000000 >> 6) == 1){
    if(millis() - last_time >= debounce_delay){
      button3Pressed = !button3Pressed;
      data = 3;
      last_time = millis();
      }
  }
  else if ((PIND >> 7 & 0b10000000 >> 7) == 1){
    if(millis() - last_time >= debounce_delay){
      button4Pressed = !button4Pressed;
      data = 4;
      last_time = millis();
      }
  }
}

ISR(PCINT0_vect) {
  if ((PINB >> 0 & 0b00000001 >> 0) == 1){
    if(millis() - last_time >= debounce_delay){
      button5Pressed = !button5Pressed;
      data = 5;
      last_time = millis();
      }
  }
  else if ((PINB >> 1 & 0b00000010 >> 1) == 1){
    if(millis() - last_time >= debounce_delay){
      button6Pressed = !button6Pressed;
      data = 6;
      last_time = millis();
      }
  }
}


void setup() {
    // Inisialisasi komunikasi I2C
    Wire.begin();

    PCICR |= (1 << PCIE2)|(1<<PCIE0); //enable untuk portB dan D
    PCMSK2 |= (1 << PCINT20) | (1 << PCINT21) | (1 << PCINT22) | (1 << PCINT23);
    PCMSK0 |= (1 << PCINT0) | (1 << PCINT1);

    // Inisialisasi pin tombol sebagai input dengan pull-up resistor
    DDRD &= ~(1 << DDD4) | ~(1 << DDD5) | ~(1 << DDD6) | ~(1 << DDD7);//input D4-D7
    PORTD |= (1 << PD4 | 1 << PD5 | 1 << PD6 | 1 << PD7);//pull-up resistor
    DDRB &= ~(1 << DDB0) | ~(1 << DDB1); //input D8&D9
    PORTB |= (1 << PB0 | 1 << PB1); //pull-up resitor
    // Mengatur interrupt untuk tombol

    sei();

    Serial.begin(9600); // Initialize serial communication for debugging
}

void loop() {
    // Mengirim data melalui I2C jika tombol ditekan
    Wire.beginTransmission(SLAVE_ADDRESS);
    Wire.write(data);
    Wire.endTransmission();
    Serial.print("terkirim: ");
    Serial.println(data); // For debugging
    delay(500);
}

slave's code:

#include <Wire.h>

const uint8_t ALAMAT_SLAVE = 0x04;

uint16_t A0_adc, A1_adc;
uint16_t duty_cycle1, duty_cycle2;

#define MOTOR1IN1 PD4
#define MOTOR1IN2 PD5
#define MOTOR2IN3 PD6
#define MOTOR2IN4 PD7
#define MOTOR1ENA PB1 //OC1A (D9)
#define MOTOR2ENB PB2 //OC1B (D10)

volatile int perintahditerima = 0;


void setupPWM() {
  // Configure Timer1 for Phase Correct PWM with ICR1 as TOP
  TCNT1 = 0;
  TCCR1A = 0;
  TCCR1B = 0;

  // Non-inverting PWM
  TCCR1A |= (1<<COM1A1)|(1<<COM1B1)|(1<<WGM11);
  // set mode 10 (phase correct PWM TOP = ICR1) prescaler = 64
  TCCR1B |= (1<<WGM13)|(1<<CS11)|(1<<CS10);
  ICR1 = 2499; // f = 50 Hz (20 ms pulse)
}

void eksekusiperintah(int karakter) {
  switch (karakter) {
    case 1:
      Motor1berhenti();
      break;
    case 2:
      putarMotor1CW();
      break;
    case 3:
      putarMotor1CCW();
      break;
    case 4:
      Motor2berhenti();
      break;
    case 5:
      putarMotor2CW();
      break;
    case 6:
      putarMotor2CCW();
      break;
  }
}

void Motor1berhenti() {
  PORTD &= ~((1 << MOTOR1IN1) | (1 << MOTOR1IN2)); //IN1&IN2 LOW
  OCR1A = 0; // Disable Motor1 by setting PWM to 0
}

void putarMotor1CW() {
  PORTD |= (1 << MOTOR1IN1);//IN1 high
  PORTD &= ~(1 << MOTOR1IN2);//IN2 low
  // OCR1A is already set in loop()
}

void putarMotor1CCW() {
  PORTD &= ~(1 << MOTOR1IN1); //IN1 low
  PORTD |= (1 << MOTOR1IN2); //IN2 high
  // OCR1A is already set in loop()
}

void Motor2berhenti() {
  PORTD &= ~((1 << MOTOR2IN3) | (1 << MOTOR2IN4)); //IN3&IN4 low
  OCR1B = 0; // Disable Motor2 by setting PWM to 0
}

void putarMotor2CW() {
  PORTD |= (1 << MOTOR2IN3); //IN3 high
  PORTD &= ~(1 << MOTOR2IN4); //IN4 low
  // OCR1B is already set in loop()
}

void putarMotor2CCW() {
  PORTD &= ~(1 << MOTOR2IN3); //IN3 low
  PORTD |= (1 << MOTOR2IN4); //IN4 high
  // OCR1B is already set in loop()
}

int adc_init(void) {
  ADMUX |= (1<<REFS0); 
  ADCSRA |= (1<<ADPS2)|(1<<ADPS1)|(1<<ADEN)|(1<<ADIE);
  sei();
  ADCSRA |= (1 << ADSC);

}


void setup() {
  // inisialisasi I2C sebagai penerima
  Wire.begin(ALAMAT_SLAVE);
  Wire.onReceive(ReceiveEvent);

  // Set motor pins as output
  DDRD |= (1 << MOTOR1IN1) | (1 << MOTOR1IN2) | (1 << MOTOR2IN3) | (1 << MOTOR2IN4);
  DDRB |= (1 << MOTOR1ENA) | (1 << MOTOR2ENB); // Set pin enable as output

  setupPWM();
  adc_init();
  sei(); // Enable global interrupts

  Serial.begin(9600);
}

void loop() {

  // konversi analog kepwm
  int duty_cycle1 = map(A0_adc, 0, 1023, 0, 255);
  int duty_cycle2 = map(A1_adc, 0, 1023, 0, 255);

  OCR1A = duty_cycle1; // Set PWM for Motor1 Enable
  OCR1B = duty_cycle2; // Set PWM for Motor2 Enable

  eksekusiperintah(perintahditerima); //menggerakkan arah motor
  
  // Debugging output
  Serial.print("Karakter: ");
  Serial.println(perintahditerima);
  Serial.print("\nPot1: ");
  Serial.print(A0_adc);
  Serial.print(" PWM1: ");
  Serial.println(duty_cycle1);
  Serial.print("Pot2: ");
  Serial.print(A1_adc);
  Serial.print(" PWM2: ");
  Serial.println(duty_cycle2);

  delay(100);
}

void ReceiveEvent() {
  while (1 < Wire.available()) {
    perintahditerima = Wire.read();
  }
}

ISR(ADC_vect){
  uint16_t x = ADCW;
  switch(ADMUX){
  // baca ADC0
   case 0x40:
            A0_adc = x;
            ADMUX = 0x41;
            break;
    // baca ADC1
    case 0x41:
            A1_adc = x;
            ADMUX = 0x42;
            break;
    default:
            break;
  }
  // mulai kembali konversi ADC
  ADCSRA |= (1 << ADSC);
}

need to isolate the problem
have you verified the code to send msgs from master to slave?
have you verify the code to control the motor?

if (PIND & 0b00010000 ){

and so on

1 Like
void loop() {
  if (data > 0) {
    // Mengirim data melalui I2C jika tombol ditekan
    Wire.beginTransmission(SLAVE_ADDRESS);
    Wire.write(data);
    Wire.endTransmission();
    Serial.print("terkirim: ");
    Serial.println(data); // For debugging
    data = 0;
    delay(50);
  }
}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.