I want to send a command to my scooter via polidea ble but I don't know how to compose the package and encode it to base64, I tried different ways but it seems it does not work. Here is the documentation of how I need to make the package:
APP 🡪 Bluetooth
START_PACK, OPCODESEND, LENGTH, D0, CHECKSUM (START_PACK = 0x55)
OPCODESEND
0x02 – Speed Limit
D0 – 1 is 6Km/k, 2 is 12Km/h, 3 is 20Km/h, 4 is 25Km/h, 5 No speed Limit
0x03 - Change Zero Start
D0 🡪 0 Zero Start OFF, 1 Zero Start ON
0x05 –Lock Unlock Scooter
D0 🡪 0 Unlock, 1 Lock
0x06 – On/Off light from display
D0 🡪 0 light OFF, 1 light ON
For example, how should the package look to turn on the light?
My understanding of the documentation you have included, is that to turn on the light the code to create the packet in base64 would be:
import { Buffer } from "buffer";
var start_pack = 0x55;
var opcode = 0x06 // light
var action = 0x01 // On
var length = 0x01 // Length of what? action?
var checksum = start_pack + opcode + action + length
var valueBytes = Buffer.alloc(5);
valueBytes[0] = start_pack;
valueBytes[1] = opcode;
valueBytes[2] = length;
valueBytes[3] = action;
valueBytes[4] = checksum;
var valueBase64 = valueBytes.toString('base64')
console.log("Data to write: " + valueBase64)
This gave me an output of:
Data to write: VQYBAV0=
Related
Hardware: ESP32 DevKitV1, PCM5102 breakout board, SD-card adapter.
Software: Arduino framework.
For some time I am struggling with audio playback using a I2S DAC external to ESP32.
The problem is I can only play without distortion for low sample frequencies, i.e. below 20kSps.
I have been studying the documentation, https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/peripherals/i2s.html, and numerous other sources but sill haven't managed to fix this.
I2S configuration function:
esp_err_t I2Smixer::i2sConfig(int bclkPin, int lrckPin, int dinPin, int sample_rate)
{
// i2s configuration: Tx to ext DAC, 2's complement 16-bit PCM, mono,
const i2s_config_t i2s_config = {
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX | I2S_CHANNEL_MONO), // only tx, external DAC
.sample_rate = sample_rate,
.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
.channel_format = I2S_CHANNEL_FMT_ONLY_RIGHT, // single channel
// .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, //2-channels
.communication_format = (i2s_comm_format_t)(I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB),
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL3, // highest interrupt priority that can be handeled in c
.dma_buf_count = 128, //16,
.dma_buf_len = 128, // 64
.use_apll = false,
.tx_desc_auto_clear = true};
const i2s_pin_config_t pin_config = {
.bck_io_num = bclkPin, //this is BCK pin
.ws_io_num = lrckPin, // this is LRCK pin
.data_out_num = dinPin, // this is DATA output pin
.data_in_num = I2S_PIN_NO_CHANGE // Not used
};
esp_err_t ret1 = i2s_driver_install((i2s_port_t)i2s_num, &i2s_config, 0, NULL);
esp_err_t ret2 = i2s_set_pin((i2s_port_t)i2s_num, &pin_config);
esp_err_t ret3 = i2s_set_sample_rates((i2s_port_t)i2s_num, sample_rate);
// i2s_adc_disable((i2s_port_t)i2s_num);
// esp_err_t ret3 = rtc_clk_apll_enable(1, 15, 8, 5, 6);
return ret1 + ret2 + ret3;
}
A wave file, which was created in a 16 bit mono PCM, 44.1kHz format, is opened:
File sample_file = SD.open("/test.wav")
In the main loop, the samples are fed to the I2S driver.
esp_err_t I2Smixer::loop()
{
esp_err_t ret1 = ESP_OK, ret2 = ESP_OK;
int32_t output = 0;
if (sample_file.available())
{
if (sample_file.size() - sample_file.position() > 2) // bytes left
{
int16_t tmp; // 16 bits signed PCM assumed
sample_file.read((uint8_t *)&tmp, 2);
output =(int32_t)tmp;
}
else
{
sample_file.close();
}
}
size_t i2s_bytes_write;
int16_t int16_t_output = (int16_t)output;
ret1 = i2s_write((i2s_port_t)i2s_num, &int16_t_output, 2, &i2s_bytes_write, portMAX_DELAY);
if (i2s_bytes_write != 2)
ret2 = ESP_FAIL;
return ret1 + ret2;
}
This works fine for sample rates up to 20 kSps.
For a sample rate of 32k or 44.1k heavy distortion occurs. I suspect that this is caused by the I2S DMA Tx buffer.
If the number of DMA buffers (dma_buf_count) and the buffer length (dma_buf_len) is increased, then the sound is played fine at first. Subsequently, after a short time, the distortion kicks in again. I cannot measure this short time span, maybe around a second, but I did notice it depends on the dma_buf_count and dma_buf_len.
Next to this, I tried increasing the CPU frequency to 240MHz, no improvement.
Further I tried to play a file from SPIFSS, no improvement.
I am out of ideas right now, has anyone encountered this issue also?
Reading one sample at a time and pushing it to the I2S driver will not be the most efficient usage of the driver. You are using just 2 bytes in every 128 byte DMA buffer. That leaves just a single sample period to push the next sample before the DMA buffer is "starved".
Read the file in 128 byte (64 sample) chunks and write the whole chunk to the I2S in order to use the DMA effectively.
Depending on the file-system implementation it may be a little more efficient too to use larger chunks that are sympathetic to the file-system's media, sector size and DMA buffering.
Edit: I solved UART communication problem but I have new problem getting pwm signal after receiving Transmit Data. I can blink led I can drive relay with transmitted data but I could not produce PWM signal.
maps(120, 1, 1, 250, RxData[4]);
ADC_Left = Yx; __HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_1,ADC_Left);
I used __HAL_TIM_SET_COMPARE function but it doesnt work. I can observe ADC_Left’s value on Debug site but its not work.
I am trying to realize UART communication between 2 stm32. I know there are several topic related with but my question focused another one.
I am reading 2 adc value on stm32 which is only transmit these value and other one only receive these 2 adc value. To do this
MX_USART1_UART_Init();
__HAL_UART_ENABLE_IT(&huart1, UART_IT_RXNE); // Interrupt Enable
__HAL_UART_ENABLE_IT(&huart1, UART_IT_TC);
char TxData1[10];
..............
TxData1[0] = 0xEA;
TxData1[1] = wData.Byte_1;
TxData1[2] = wData.Byte_2;
TxData1[3] = wData.Byte_3;
TxData1[4] = wData.Right_Adc_Val;
TxData1[5] = wData.Left_Adc_Val;
TxData1[6] = wData.Byte_6;
for(uint8_t i = 1 ; i < 7; i++)
{
wData.Checksum = wData.Checksum + TxData1[i];
}
wData.Checksum_H = (wData.Checksum >> 8)&0xFF;
wData.Checksum_L = (wData.Checksum)&0xFF;
TxData1[7] = wData.Checksum_H;
TxData1[8] = wData.Checksum_L;
TxData1[9] = 0xAE;
HAL_UART_Transmit_IT(&huart1,(uint8_t*) &TxData1,10);
............
This block sent them I can observate them on Debug screen and using TTL module's Tx Rx pins.
MX_USART1_UART_Init();
__HAL_UART_ENABLE_IT(&huart1, UART_IT_RXNE); // Interrupt Enable
__HAL_UART_ENABLE_IT(&huart1, UART_IT_TC);
char RxData[10];
while(1){
HAL_UART_Receive_IT(&huart1,(uint8_t*) &RxData,10);
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance == USART1)
{
HAL_UART_Receive_IT(&huart1,(uint8_t*) &RxData,10);
}
There is no problem up to here but when i getting RxData 0. index , it gives EA . Of course it should be give EA. When the adc data change all the ranking is changing. RxData[0] gives meaningless data. adc value is jumping over the all RxData array.
data locations must always be in the same index. How Can I get these data in stability for ex.
RxData[0]=EA
.
.
RxData[4]= should give adc value. so on.
..
Edit: I tried other mode of UART, DMA (in circular mode) and direct mode were used. I cant receive even 1 byte with DMA .
In your example code, you have an extra & that needs to be removed from both the transmit and receive HAL method calls. Example:
HAL_UART_Transmit_IT(&huart1,(uint8_t*) &TxData1,10);
HAL_UART_Transmit_IT(&huart1,(uint8_t*) TxData1,10);
To avoid this type of error in the future, recommend not using the cast and try something like the following:
uint8_t TxData1[10];
...
HAL_UART_Transmit_IT(&huart1, TxData1, sizeof(TxData1);
I'm trying to decipher data sent on the USB bus by an HID device (an Eaton power supply to be precise)
Using Wireshark, I can capture the USB traffic. When the device is connected, I can see the HID descriptor being sent. I can parse it alright, and thanks to an external reference (http://networkupstools.org/protocols/mge/NUT_MGE_USB_Devices_Draft_AA.pdf and http://www.usb.org/developers/docs/devclass_docs/pdcv10.pdf), I've got some info regarding the different fields of the descriptor.
However, I can't seem to link the descriptor to the data inside the frames I actually capture with Wireshark: I can't really make out any clear header or pattern in the messages, tied to the descriptor.
In this case, I see quite a bunch of URB Control Response messages, which probably contain the data I want, but which message contains which info is unclear.
Does anyone have some sort of method to reverse-engineer and parse the data sent by a USB HID device ?
Thanks
I wrote a bit of code a while back to help me decode HID report descriptors and to create C language structure definitions to describe each report. What I would do is:
capture the USB data using Wireshark
filter on "usb.request_in"
select the "GET DESCRIPTOR Response HID Report" packet
right-click the "HID Report" and choose "Copy" and "...as a Hex Stream"
Now run the decoding software and paste the hex stream after the "-c" option. For example:
rexx rd.rex -c 05010906a101854b050719e029e7250175019508810275089501810326ff0019002aff0081007501950305081901290325019102750595019103c005010902a1010901a100854d09301581257f750895018106c0c0
It will by default print the C-structures (see below). If you want to also decode the HID report descriptors then use the "-d" option.
//--------------------------------------------------------------------------------
// Keyboard/Keypad Page inputReport 4B (Device --> Host)
//--------------------------------------------------------------------------------
typedef struct
{
uint8_t reportId; // Report ID = 0x4B (75) 'K'
// Collection: Keyboard
uint8_t KB_KeyboardKeyboardLeftControl : 1; // Usage 0x000700E0: Keyboard Left Control, Value = 0 to 1
uint8_t KB_KeyboardKeyboardLeftShift : 1; // Usage 0x000700E1: Keyboard Left Shift, Value = 0 to 1
uint8_t KB_KeyboardKeyboardLeftAlt : 1; // Usage 0x000700E2: Keyboard Left Alt, Value = 0 to 1
uint8_t KB_KeyboardKeyboardLeftGui : 1; // Usage 0x000700E3: Keyboard Left GUI, Value = 0 to 1
uint8_t KB_KeyboardKeyboardRightControl : 1; // Usage 0x000700E4: Keyboard Right Control, Value = 0 to 1
uint8_t KB_KeyboardKeyboardRightShift : 1; // Usage 0x000700E5: Keyboard Right Shift, Value = 0 to 1
uint8_t KB_KeyboardKeyboardRightAlt : 1; // Usage 0x000700E6: Keyboard Right Alt, Value = 0 to 1
uint8_t KB_KeyboardKeyboardRightGui : 1; // Usage 0x000700E7: Keyboard Right GUI, Value = 0 to 1
uint8_t pad_2; // Pad
uint8_t KB_Keyboard; // Value = 0 to 255
} inputReport4B_t;
//--------------------------------------------------------------------------------
// LED Indicator Page outputReport 4B (Device <-- Host)
//--------------------------------------------------------------------------------
typedef struct
{
uint8_t reportId; // Report ID = 0x4B (75) 'K'
// Collection: Keyboard
uint8_t LED_KeyboardNumLock : 1; // Usage 0x00080001: Num Lock, Value = 0 to 1
uint8_t LED_KeyboardCapsLock : 1; // Usage 0x00080002: Caps Lock, Value = 0 to 1
uint8_t LED_KeyboardScrollLock : 1; // Usage 0x00080003: Scroll Lock, Value = 0 to 1
uint8_t : 5; // Pad
} outputReport4B_t;
//--------------------------------------------------------------------------------
// Generic Desktop Page inputReport 4D (Device --> Host)
//--------------------------------------------------------------------------------
typedef struct
{
uint8_t reportId; // Report ID = 0x4D (77) 'M'
// Collection: Mouse Pointer
int8_t GD_MousePointerX; // Usage 0x00010030: X, Value = -127 to 127
} inputReport4D_t;
Now that you have a clear idea of the possible reports that may be flowing, you can go back to your Wireshark trace (still filtered on "usb.request_in") and select "URB_INTERRUPT in" packets. The "Leftover Capture Data" should contain the payload as described by one of the C structures.
Hope this helps.
I have implemented the following code on an embedded platform that attempts to communicate with an XBee. The embedded platform that executes the code below is not an xbee:
int main()
{
char payload[12] = {0x61,0x88,0x00,0x64,0x00,0x00,0x00,0x00,0x00,0xEC,0x00,0x00}
payload[2] = 0x10;
payload[9] = 0x01;
char data = 'H'; // Send simple ASCII character to XBee
payload[11]= data;
while (1)
sendByteofData(payload,12);
}
void sendByteOfData(char * payload, int len)
{
int x;
for (x=0;x<4;x++)
// This function sends IEEE 802.15.4 frames, and I know it
// works because they are detected in the [sniffer][3].
send_IEEE_802_15_4_frame(payload,len);
}
payload[2] = payload[2] % 256 + 1;
payload[9] = payload[9] % 256 + 1;
if (payload[9] % 256 == 0 )
payload[9] = 0x01;
else
payload[9] %= 256;
}
To my surprise the above code actually sent one byte from the embedded platform to the XBee successfully. however, the infinite loop at the end of main() should have produced a stream of bytes.
My suspicion is I need to set payload[2] and payload[9] correctly, and there is probably a flaw in the incremental modulo 256 algorithm shown above.
How do I get a continuous stream of bytes?
A few thoughts...
Make your payload an array of unsigned char or, even better, uint8_t.
To update payload[2] and payload[9], simplify your code:
++payload[2];
++payload[9];
if (payload[9] == 0) payload[9] = 1;
Add a delay between sends. You might even need to wait for a response before sending the next character.
Since it's a payload of unsigned 8-bit values, they'll automatically roll from 255 to 0. I assume your special case code for payload[9] is trying to roll from 255 to 1 (instead of 0).
Make sure your payload doesn't need to include a checksum of some sort. Updating those two bytes would have an affect on a checksum byte.
/* INPUT PINS */
PIN 1 = clock; /* clock input*/
/**************** OUTPUT PINS *********************/
PIN 14 = Q1 ; /*output*/
PIN 15 = Q2 ; /*output*/
Q1.ck = clock;
Q1.d = !Q1;
Q2.d = !Q2;
This is my code and the two lines below the output pins create a 1 bit ripple counter but I'm unsure how to transfer the output of the first flip flop to be the clock input for the second flip flop. The chip I'm trying to program is an Atmel ATF750C chip.
The device does not allow separate clock definitions for individual flip-flops. The clock input to pin 1 is a shared clock for all flip-flops in the device. You could try the following instead:
Device = G16V8;
/* Inputs */
Pin 1 = CLK; /* clock source */
Pin 11 = GND; /* ground this for registered operation */
/* Outputs */
Pin 12 = Q0;
Pin 13 = Q1;
Pin 14 = Q2;
Pin 15 = Q3;
/* Equations */
!Q0.d = !Q3;
Q0.oe = 'b'1; /* output enabled - also default */
!Q1.d = Q0;
Q1.oe = 'b'1; /* output enabled - also default */
!Q2.d = Q1;
Q2.oe = 'b'1; /* output enabled - also default */
!Q3.d = Q2;
Q3.oe = 'b'1; /* output enabled - also default */
Note: The above example would provide a 4-bit ripple binary counter/divider.
For instance: An 8MHz clock input would be divided by 8 resulting in 4 shifted 1MHz outputs on each Q pin.
Wincupl is a sort of primitive vhdl, but I have now figured it out. I just had to append ".d" to my output variables, then attached my clock to pin #1 and ground pin #11. And yeah I did have to get intimate with the GAL16v8 and WinCUPL documentation to figure it all out.
/******** OUTPUT PINS **********/
PIN 14 = Q1.d;
PIN 15 = Q2.d;
Q1.ck = clock;
!Q1.d = Q1;
Q2.ck = !Q1;
!Q2.d = Q2;
This creates an asynchronous ripple counter that counts up in binary using D flip flops.