diff --git a/frtos/barcode_sensor/CMakeLists.txt b/frtos/barcode_sensor/CMakeLists.txt new file mode 100644 index 0000000..e61432b --- /dev/null +++ b/frtos/barcode_sensor/CMakeLists.txt @@ -0,0 +1,19 @@ +add_executable( + barcode_sensor_test + barcode_sensor_test.c +) + +target_link_libraries( + barcode_sensor_test + hardware_adc + pico_stdlib + FreeRTOS-Kernel-Heap4 # FreeRTOS kernel and dynamic heap +) + +target_include_directories(barcode_sensor_test + PRIVATE ../config + ../line_sensor +) + +pico_enable_stdio_usb(barcode_sensor_test 1) +pico_add_extra_outputs(barcode_sensor_test) \ No newline at end of file diff --git a/frtos/barcode_sensor/barcode_sensor.h b/frtos/barcode_sensor/barcode_sensor.h new file mode 100644 index 0000000..1a95a67 --- /dev/null +++ b/frtos/barcode_sensor/barcode_sensor.h @@ -0,0 +1,124 @@ +/* Barcode sensor */ + +#include "barcode_sensor_init.h" + +#define MAX_BARCODES 10 // Define the maximum number of barcodes to store +#define BARCODE_SENSOR_TIMER_PERIOD_MS 100 // Define the barcode sensor timer period + +// Define the barcode sensor timer +static struct repeating_timer barcode_sensor_timer; + + +/** + * @brief Decode a Code 39 barcode + * + * This function decodes a Code 39 barcode represented as a 9-bit binary number. + * + * @param barcode_data Binary representation of the barcode data (9 bits) + * @return Decoded value as an integer + */ +int code39_decode(uint32_t barcode_data) { + // Define the binary representations of Code 39 characters + const uint32_t code39_characters[] = { + 0b001001001, // 0 + 0b001001011, // 1 + 0b001011001, // 2 + 0b001011011, // 3 + 0b001100011, // 4 + 0b001101001, // 5 + 0b001101011, // 6 + 0b001010011, // 7 + 0b001011101, // 8 + 0b001111001, // 9 + // Add more character representations as needed + }; + + // Compare the barcode data to known Code 39 character representations + for (int i = 0; i < 10; i++) { + if (barcode_data == code39_characters[i]) { + return i; // Return the decoded value (0-9) + } + } + + // If the barcode data does not match any known character, return -1 to indicate an error + return -1; +} + + +/** + * @brief Monitor the barcode sensor + * + * This function will monitor the barcode sensor and send the state to the + * barcode sensor message buffer, including Code 39 decoding. + * + * @param params + */ +void monitor_barcode_sensor_task(void *params) { + // Create the barcode sensor timer + add_repeating_timer_ms(BARCODE_SENSOR_TIMER_PERIOD_MS, h_barcode_sensor_timer_handler, NULL, &barcode_sensor_timer); + + for (;;) { + if (xSemaphoreTake(g_barcode_sensor_sem, portMAX_DELAY) == pdTRUE) { + // Check the flag or receive the message + if (barcode_sensor_triggered == pdTRUE) { + uint32_t barcode_data = 0; + int bar_width = 0; // Variable to store the width of the current bar + + for (int i = 0; i < 9; i++) { + sleep_ms(100); // Wait for a segment of the barcode + + // Measure bar width using the IR sensor + if (gpio_get(BARCODE_SENSOR_PIN)) { + bar_width++; + } else { + // Bar ended, process the width + if (bar_width > 0) { + printf("Bar Width: %d\n", bar_width); + // Process or store the bar width as needed + bar_width = 0; // Reset the bar width measurement + } + + barcode_data |= (1u << i); + } + } + + printf("Barcode Data (binary): %09b\n", barcode_data); + + // Decode the barcode data + int decoded_value = code39_decode(barcode_data); + + if (decoded_value != -1) { + printf("Decoded Value: %d\n", decoded_value); + // Store or process the decoded value as needed + + // Send the decoded value instead of the raw barcode data + xMessageBufferSend(barcode_sensor_msg_buffer, &decoded_value, sizeof(int), 0); + } else { + printf("Error: Unable to decode the barcode.\n"); + } + + // Reset the flag + barcode_sensor_triggered = pdFALSE; + } + } + } +} + + + + +/** + * @brief Monitor the barcode sensor + * @param params + */ +void +monitor_barcode_task(__unused void *params) { + state_t barcode_state; + + // Receive from Buffer + xMessageBufferReceive(barcode_sensor_msg_buffer, + &barcode_state, + sizeof(state_t), + portMAX_DELAY); + +} \ No newline at end of file diff --git a/frtos/barcode_sensor/barcode_sensor_init.h b/frtos/barcode_sensor/barcode_sensor_init.h new file mode 100644 index 0000000..e33041e --- /dev/null +++ b/frtos/barcode_sensor/barcode_sensor_init.h @@ -0,0 +1,97 @@ +/* Initialise the barcode sensor */ + +#ifndef BARCODE_SENSOR_INIT_H +#define BARCODE_SENSOR_INIT_H + +#include +#include "pico/stdlib.h" + +#include "hardware/adc.h" + +#include "FreeRTOS.h" +#include "task.h" +#include "message_buffer.h" +#include "semphr.h" + +#include "barcode_sensor_config.h" +#include "line_sensor_init.h" + +// Set barcode time to 0 +static TickType_t lastBarcodeTime = 0; + + +// Semaphore +SemaphoreHandle_t g_barcode_sensor_sem = NULL; + + +// Queue +static MessageBufferHandle_t barcode_sensor_msg_buffer; // Barcode Sensor Buffer + +// Flag +static volatile BaseType_t barcode_sensor_triggered = pdFALSE; + + +/** + * @brief Setup the Line Sensor + * + * This function will setup the Line Sensor by initializing it as an input + */ +static inline void +barcode_sensor_setup() { + g_barcode_sensor_sem = xSemaphoreCreateBinary(); + + + uint mask = (1 << BARCODE_SENSOR_PIN); + + // Initialise 3 GPIO pins and set them to input + gpio_init_mask(mask); + gpio_set_dir_in_masked(mask); + + barcode_sensor_msg_buffer = xMessageBufferCreate(30); + +} + +/** + * @brief Timer Interrupt Handler for the barcode sensor + * + * @param repeatingTimer + * @return True (To keep the timer running) + */ +bool h_barcode_sensor_timer_handler(repeating_timer_t *repeatingTimer) { + + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + xSemaphoreGiveFromISR(g_barcode_sensor_sem, + &xHigherPriorityTaskWoken); + portYIELD_FROM_ISR(xHigherPriorityTaskWoken); + + return true; +} + +void h_barcode_sensor_handler(void) { + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + TickType_t currentTicks = xTaskGetTickCount(); + printf("Interrupt triggered\n"); + + if (gpio_get_irq_event_mask(BARCODE_SENSOR_PIN) & GPIO_IRQ_EDGE_FALL) + { + if ((currentTicks - lastBarcodeTime) >= + pdMS_TO_TICKS(DEBOUNCE_DELAY_MS)) + { + lastBarcodeTime = currentTicks; + gpio_acknowledge_irq(BARCODE_SENSOR_PIN, GPIO_IRQ_EDGE_FALL); + // Set the flag to notify the task + barcode_sensor_triggered = pdTRUE; + xSemaphoreGiveFromISR(g_barcode_sensor_sem, + &xHigherPriorityTaskWoken); + } + else + { + // Reset the timer to the currentTicks if the edge is ignored + lastBarcodeTime = currentTicks; + } + } + + portYIELD_FROM_ISR(xHigherPriorityTaskWoken); +} + +#endif /* LINE_SENSOR_INIT_H */ diff --git a/frtos/barcode_sensor/barcode_sensor_test.c b/frtos/barcode_sensor/barcode_sensor_test.c new file mode 100644 index 0000000..1aa45b4 --- /dev/null +++ b/frtos/barcode_sensor/barcode_sensor_test.c @@ -0,0 +1,48 @@ +#include "barcode_sensor.h" + +#define READ_BARCODE_SENSOR_PRIO (tskIDLE_PRIORITY + 2UL) + +void +launch() +{ + // isr to detect left line sensor + gpio_set_irq_enabled(BARCODE_SENSOR_PIN, GPIO_IRQ_EDGE_FALL, true); + gpio_add_raw_irq_handler(BARCODE_SENSOR_PIN, h_barcode_sensor_handler); + + + irq_set_enabled(IO_IRQ_BANK0, true); + + + struct repeating_timer g_barcode_sensor_timer; + add_repeating_timer_ms(LINE_SENSOR_READ_DELAY, + h_barcode_sensor_timer_handler, + NULL, + &g_barcode_sensor_timer); + + + TaskHandle_t h_monitor_barcode_sensor_task; + xTaskCreate(monitor_barcode_sensor_task, + "Monitor Barcode Sensor Task", + configMINIMAL_STACK_SIZE, + NULL, + READ_BARCODE_SENSOR_PRIO, + &h_monitor_barcode_sensor_task); + + vTaskStartScheduler(); +} + +int +main (void) +{ + stdio_usb_init(); + + sleep_ms(10000); + printf("Test started!\n"); + + barcode_sensor_setup(); + initialize_car_state(); + + launch(); + + return (0); +} \ No newline at end of file diff --git a/frtos/config/motor_config.h b/frtos/config/motor_config.h index 38a81ea..0572d4c 100644 --- a/frtos/config/motor_config.h +++ b/frtos/config/motor_config.h @@ -13,17 +13,10 @@ #define DIRECTION_PIN_LEFT_IN3 19U #define DIRECTION_PIN_LEFT_IN4 20U -#define DIRECTION_RIGHT_FORWARD (1U << DIRECTION_PIN_RIGHT_IN2) -#define DIRECTION_RIGHT_BACKWARD (1U << DIRECTION_PIN_RIGHT_IN1) -#define DIRECTION_LEFT_FORWARD (1U << DIRECTION_PIN_LEFT_IN4) -#define DIRECTION_LEFT_BACKWARD (1U << DIRECTION_PIN_LEFT_IN3) - -#define DIRECTION_FORWARD (DIRECTION_RIGHT_FORWARD | DIRECTION_LEFT_FORWARD) -#define DIRECTION_BACKWARD (DIRECTION_RIGHT_BACKWARD | DIRECTION_LEFT_BACKWARD) -#define DIRECTION_LEFT (DIRECTION_RIGHT_FORWARD | DIRECTION_LEFT_BACKWARD) -#define DIRECTION_RIGHT (DIRECTION_RIGHT_BACKWARD | DIRECTION_LEFT_FORWARD) - -#define DIRECTION_MASK (DIRECTION_FORWARD | DIRECTION_BACKWARD) +#define DIRECTION_RIGHT_FORWARD (1U << DIRECTION_PIN_RIGHT_IN2) +#define DIRECTION_RIGHT_BACKWARD (1U << DIRECTION_PIN_RIGHT_IN1) +#define DIRECTION_LEFT_FORWARD (1U << DIRECTION_PIN_LEFT_IN4) +#define DIRECTION_LEFT_BACKWARD (1U << DIRECTION_PIN_LEFT_IN3) #define SPEED_PIN_RIGHT 15U #define SPEED_PIN_LEFT 16U diff --git a/frtos/motor/motor_speed.h b/frtos/motor/motor_speed.h index 9b556ec..230a596 100644 --- a/frtos/motor/motor_speed.h +++ b/frtos/motor/motor_speed.h @@ -72,53 +72,4 @@ monitor_wheel_speed_task(void *pvParameters) p_motor->speed.current_cms = 0.f; } } -} - -void -set_wheel_speed(uint32_t pwm_level, motor_t * motor) -{ - motor->pwm.level = pwm_level; - - pwm_set_chan_level(motor->pwm.slice_num, - motor->pwm.channel, - motor->pwm.level); -} - -/*! - * @brief Set the speed of the wheels - * @param pwm_level The pwm_level of the wheels, from 0 to 99 - */ -void -set_wheel_speed_synced(uint32_t pwm_level) -{ - if (pwm_level > MAX_PWM_LEVEL) - { - pwm_level = MAX_PWM_LEVEL; - } - - set_wheel_speed(pwm_level, &g_motor_left); - set_wheel_speed(pwm_level, &g_motor_right); -} - -/*! - * @brief Set the distance to travel before stopping, must be called after - * setting the speed and direction. - * @param distance_cm distance to travel in cm - */ -void -distance_to_stop(float distance_cm) -{ - float initial = g_motor_right.speed.distance_cm; - - for (;;) - { - if (g_motor_right.speed.distance_cm - initial >= distance_cm) - { - set_wheel_speed_synced(0u); - break; - } - vTaskDelay(pdMS_TO_TICKS(10)); - } - vTaskDelay(pdMS_TO_TICKS(1000)); - g_motor_right.speed.distance_cm = g_motor_left.speed.distance_cm; -} +} \ No newline at end of file