This commit is contained in:
soapysoltionss 2023-11-07 13:08:15 +08:00
commit 57683829ae
6 changed files with 293 additions and 61 deletions

View File

@ -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)

View File

@ -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);
}

View File

@ -0,0 +1,97 @@
/* Initialise the barcode sensor */
#ifndef BARCODE_SENSOR_INIT_H
#define BARCODE_SENSOR_INIT_H
#include <stdio.h>
#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 */

View File

@ -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);
}

View File

@ -18,13 +18,6 @@
#define DIRECTION_LEFT_FORWARD (1U << DIRECTION_PIN_LEFT_IN4) #define DIRECTION_LEFT_FORWARD (1U << DIRECTION_PIN_LEFT_IN4)
#define DIRECTION_LEFT_BACKWARD (1U << DIRECTION_PIN_LEFT_IN3) #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 SPEED_PIN_RIGHT 15U #define SPEED_PIN_RIGHT 15U
#define SPEED_PIN_LEFT 16U #define SPEED_PIN_LEFT 16U

View File

@ -73,52 +73,3 @@ monitor_wheel_speed_task(void *pvParameters)
} }
} }
} }
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;
}