diff --git a/src/html/web_portal.html b/src/html/web_portal.html index 593b82a..c475977 100644 --- a/src/html/web_portal.html +++ b/src/html/web_portal.html @@ -111,6 +111,7 @@ + diff --git a/src/jm_science_scale.c b/src/jm_science_scale.c new file mode 100644 index 0000000..8e98df7 --- /dev/null +++ b/src/jm_science_scale.c @@ -0,0 +1,109 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hardware/uart.h" +#include "configuration.h" +#include "scale.h" +#include "app.h" + + +typedef union { + struct __attribute__((__packed__)){ + char header; + char _space; + char stable_state; + char symbol; + char weighing_data[9]; + char _space2; + char weighing_unit[3]; + char terminator[2]; + }; + char bytes[19]; +} jm_science_frame_data_format_t; + + +const static char JM_SCIENCE_FRAME_HEADER = 'E'; + + +// Forward declaration +void _jm_science_scale_listener_task(void *p); +static void force_zero(); + +extern scale_config_t scale_config; + +// Instance of the scale handle for JM Sciense FA series +scale_handle_t jm_science_scale_handle = { + .read_loop_task = _jm_science_scale_listener_task, + .force_zero = force_zero, +}; + + +static float _decode_measurement_msg(jm_science_frame_data_format_t * frame) { + // decode sign + int sign = 1; + if (frame->symbol == '-') { + sign = -1; + } + + // Decode weight information + char *endptr; + float weight = strtof(frame->weighing_data, &endptr); + + if( endptr == frame->weighing_data ) { + // Conversion failed + return nanf(frame->weighing_data); + } + + weight *= sign; + + return weight; +} + + +void _jm_science_scale_listener_task(void *p) { + jm_science_frame_data_format_t frame; + uint8_t byte_idx = 0; + + while (true) { + // Read all data + while (uart_is_readable(SCALE_UART)) { + char ch = uart_getc(SCALE_UART); + + // Determine if the frame header is received + // If a header is received then we should reset the decode sequence + if (ch == JM_SCIENCE_FRAME_HEADER) { + byte_idx = 0; + } + + frame.bytes[byte_idx++] = ch; + + // If we have received 17 bytes then we can decode the message + if (byte_idx == sizeof(jm_science_frame_data_format_t)) { + // Data is ready, send to decode + scale_config.current_scale_measurement = _decode_measurement_msg(&frame); + + // Signal the data is ready + if (scale_config.scale_measurement_ready) { + xSemaphoreGive(scale_config.scale_measurement_ready); + } + + // Reset buffer index to avoid overflow + byte_idx = 0; + } + } + + vTaskDelay(pdMS_TO_TICKS(20)); + } +} + + +static void force_zero() { + // Unsupported +} + diff --git a/src/scale.c b/src/scale.c index 5436c8f..f566af6 100644 --- a/src/scale.c +++ b/src/scale.c @@ -16,6 +16,8 @@ extern scale_handle_t and_fxi_scale_handle; extern scale_handle_t steinberg_scale_handle; extern scale_handle_t ussolid_scale_handle; extern scale_handle_t gng_scale_handle; +extern scale_handle_t jm_science_scale_handle; + scale_config_t scale_config; @@ -35,14 +37,19 @@ void set_scale_driver(scale_driver_t scale_driver) { scale_config.scale_handle = &steinberg_scale_handle; break; } + case SCALE_DRIVER_GNG_JJB: + { + scale_config.scale_handle = &gng_scale_handle; + break; + } case SCALE_DRIVER_USSOLID_JFDBS: { scale_config.scale_handle = &ussolid_scale_handle; break; } - case SCALE_DRIVER_GNG_JJB: + case SCALE_DRIVER_JM_SCIENCE: { - scale_config.scale_handle = &gng_scale_handle; + scale_config.scale_handle = &jm_science_scale_handle; break; } default: @@ -88,6 +95,8 @@ const char * get_scale_driver_string() { case SCALE_DRIVER_GNG_JJB: scale_driver_string = "GNG JJB"; break; + case SCALE_DRIVER_JM_SCIENCE: + scale_driver_string = "JM SCIENCE"; default: break; } diff --git a/src/scale.h b/src/scale.h index e66e881..14f0a68 100644 --- a/src/scale.h +++ b/src/scale.h @@ -31,6 +31,7 @@ typedef enum { SCALE_DRIVER_STEINBERG_SBS = 1, SCALE_DRIVER_GNG_JJB = 2, SCALE_DRIVER_USSOLID_JFDBS = 3, + SCALE_DRIVER_JM_SCIENCE = 4, } scale_driver_t;