Trouble playing WAV on ESP32 using I2S with internal DAC - audio

I'm trying to use I2S and internal DAC to play WAV files from SPIFF on a Heltec WiFi LoRa 32 V2, using the Arduino IDE.
I have an audio amp and an oscilloscope hooked up to DAC2 (pin 25) of the board and I'm not getting any signal. I've simplified the problem by generating a sine wave (as in the ESP-IDF examples). Here's the code:
#include <Streaming.h>
#include <driver/i2s.h>
#include "freertos/queue.h"
#define SAMPLE_RATE (22050)
#define SAMPLE_SIZE 4000
#define PI (3.14159265)
#define I2S_BCK_IO (GPIO_NUM_26)
#define I2S_WS_IO (GPIO_NUM_25)
#define I2S_DO_IO (GPIO_NUM_22)
#define I2S_DI_IO (-1)
size_t i2s_bytes_write = 0;
static const int i2s_num = 0;
int sample_data[SAMPLE_SIZE];
i2s_config_t i2s_config = {
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN), // Only TX
.sample_rate = SAMPLE_RATE,
.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, //2-channels
.communication_format = (i2s_comm_format_t)I2S_COMM_FORMAT_I2S,
.intr_alloc_flags = 0,//ESP_INTR_FLAG_LEVEL1
.dma_buf_count = 8,
.dma_buf_len = 64,
.use_apll = false //Interrupt level 1
};
i2s_pin_config_t pin_config = {
.bck_io_num = I2S_BCK_IO,
.ws_io_num = I2S_WS_IO,
.data_out_num = I2S_DO_IO,
.data_in_num = I2S_DI_IO //Not used
};
static void setup_sine_wave()
{
unsigned int i;
int sample_val;
double sin_float;
size_t i2s_bytes_write = 0;
for (i = 0; i < SAMPLE_SIZE; i++)
{
sin_float = sin(i * PI / 180.0);
sin_float *= 127;
sample_val = (uint8_t)sin_float;
sample_data[i] = sample_val;
Serial << sample_data[i] << ",";
delay(1);
}
Serial << endl << "Sine wave generation complete" << endl;
}
void setup() {
pinMode(26, OUTPUT);
Serial.begin(115200);
i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);
//i2s_set_pin(I2S_NUM_0, NULL);
i2s_set_pin(I2S_NUM_0, &pin_config);
i2s_set_dac_mode(I2S_DAC_CHANNEL_RIGHT_EN);
i2s_set_sample_rates(I2S_NUM_0, 22050); //set sample rates
setup_sine_wave();
i2s_set_clk(I2S_NUM_0, SAMPLE_RATE, I2S_BITS_PER_SAMPLE_16BIT, I2S_CHANNEL_MONO);
i2s_write(I2S_NUM_0, &sample_data, SAMPLE_SIZE, &i2s_bytes_write, 500);
i2s_driver_uninstall(I2S_NUM_0); //stop & destroy i2s driver
}
void loop()
{
i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);
i2s_write(I2S_NUM_0, &sample_data, SAMPLE_SIZE, &i2s_bytes_write, 500);
delay(100);
i2s_driver_uninstall(I2S_NUM_0);
delay(10);
}
The code uploads and runs OK but I still get no signal on pin 25. I also looked on pin 26 (DAC1) but that seems to be used by LoRa_IRQ. Can anyone help me out?

First of all, take a look at how you've set up your pins
#define I2S_BCK_IO (GPIO_NUM_26)
#define I2S_WS_IO (GPIO_NUM_25)
#define I2S_DO_IO (GPIO_NUM_22)
#define I2S_DI_IO (-1)
According to this specification, pin 26 will output a clock signal, pin 25 will output the line selector (left or right), and pin 22 will output the serial data corresponding to the audio you're sending to your DAC.
.sample_rate = SAMPLE_RATE,
.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
Now you've set up your sample rate to 22050Hz, and your bit depth to 16 bits. So on pin 26 and 22 you should be getting a periodic signal of 22kHz, and a periodic signal of 22kHz/16 on pin 25.
Now to your problem. First, the ESP32 board has two 8-bit internal DACs, and they'll output an analog signal with a 8-bit depth. So in reality, pin 22 should be outputting an analog signal. Let's take a look at your code:
i2s_set_pin(I2S_NUM_0, &pin_config);
The I2s specification is a 3-line bus specification for audio communication. Since you're using the internal DAC, you don't need these three lines and setting their pins will make the driver assume you want to use them (meaning the DAC pin won't be activated).
//i2s_set_pin(I2S_NUM_0, NULL);
Uncomment this and the driver will assume you want to use the internal DAC.
.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
Again, since the internal DAC only takes 8 bits per sample, the driver only takes the 8 most significant bits. You can set this to 8 bits and avoid any problems.
void setup() {
pinMode(26, OUTPUT);
Serial.begin(115200);
i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);
//i2s_set_pin(I2S_NUM_0, NULL);
i2s_set_pin(I2S_NUM_0, &pin_config);
i2s_set_dac_mode(I2S_DAC_CHANNEL_RIGHT_EN);
i2s_set_sample_rates(I2S_NUM_0, 22050); //set sample rates
setup_sine_wave();
i2s_set_clk(I2S_NUM_0, SAMPLE_RATE, I2S_BITS_PER_SAMPLE_16BIT, I2S_CHANNEL_MONO);
i2s_write(I2S_NUM_0, &sample_data, SAMPLE_SIZE, &i2s_bytes_write, 500);
i2s_driver_uninstall(I2S_NUM_0); //stop & destroy i2s driver
}
In your setup function you're installing the I2s driver, then setting the pins for an I2s communication with an external DAC, setting the sample rate to 22050, resetting them to 22050 again, writing 1 cycle of your sine wave, then uninstalling the driver. After you uninstall the driver, it is useless to output anything. Here's a more appropriate approach:
void setup() {
Serial.begin(115200);
i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);
i2s_set_pin(I2S_NUM_0, NULL);
i2s_set_dac_mode(I2S_DAC_CHANNEL_BOTH_EN); // You also might be sending data to the wrong channel, so use both.
setup_sine_wave();
}
Now the loop function:
void loop()
{
i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);
i2s_write(I2S_NUM_0, &sample_data, SAMPLE_SIZE, &i2s_bytes_write, 500);
delay(100);
i2s_driver_uninstall(I2S_NUM_0);
delay(10);
}
You don't need to install and uninstall the I2s driver, nor delay the outer function, since the write function writes to a buffer that is consumed in the specified sample rate.
void loop()
{
i2s_write(I2S_NUM_0, &sample_data, SAMPLE_SIZE, &i2s_bytes_write, 500);
}
This is all you need, theorically. But there's a major problem. You defined your audio buffer as an int-array (a list of 32 bit signed values). Then you defined the size of this buffer as 4000
#define SAMPLE_SIZE 4000
In your write function, the buffer size parameter expects the size in bytes of your buffer, kinda like when you use the malloc function. Since each sample in your buffer has 4 bytes, you're only giving 1/4 of your buffer to the write function. In the end, you're not outputting a sine wave, but a 1/4 of a sine wave.
void loop()
{
i2s_write(I2S_NUM_0, &sample_data, SAMPLE_SIZE * sizeof(int), &i2s_bytes_write, 500);
}
Should do the trick.
I haven't tested this code, but hopefully my explanation will give you some directions as to debug your code.
I2s driver documentation has some code samples that you can check aswell.

Related

Alsa buffer underrun

I am trying to write random noise to to a device and allow my loop to sleep when I have written enough data. My understanding is that for each call to snd_pcm_writei I am writing 162 bytes (81 frames) which at 8khz rate and 16bit format it should be enough audio for ~10ms. I have verified that alsa does tell me I have written 81 frames.
I would expect that I can then sleep for a short amount of time before waking up and pushing the next 10 ms worth of data. However when I sleep for any amount - even a single ms - I start to get buffer underrun errors.
Obviously I have made an incorrect assumption somewhere. Can anyone point me to what I may be missing? I have removed most error checking to shorten the code - but there are no errors initializing the alsa system on my end. I would like to be able to push 10ms of audio and sleep (even for 1 ms) before pushing the next 10ms.
#include <alsa/asoundlib.h>
#include <spdlog/spdlog.h>
int main(int argc, char **argv) {
snd_pcm_t* handle;
snd_pcm_hw_params_t* hw;
unsigned int rate = 8000;
unsigned long periodSize = rate / 100; //period every 10 ms
int err = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0);
snd_pcm_hw_params_malloc(&hw);
snd_pcm_hw_params_any(handle, hw);
snd_pcm_hw_params_set_access(handle, hw, SND_PCM_ACCESS_RW_INTERLEAVED);
snd_pcm_hw_params_set_format(handle, hw, SND_PCM_FORMAT_S16_LE);
snd_pcm_hw_params_set_rate(handle, hw, rate, 0);
snd_pcm_hw_params_set_channels(handle, hw, 1);
int dir = 1;
snd_pcm_hw_params_set_period_size_near(handle, hw, &periodSize, &dir);
snd_pcm_hw_params(handle, hw);
snd_pcm_uframes_t frames;
snd_pcm_hw_params_get_period_size(hw, &frames, &dir);
int size = frames * 2; // two bytes a sample
char* buffer = (char*)malloc(size);
unsigned int periodTime;
snd_pcm_hw_params_get_period_time(hw,&periodTime, &dir);
snd_pcm_hw_params_free(hw);
snd_pcm_prepare(handle);
char* randomNoise = new char[size];
for(int i = 0; i < size; i++)
randomNoise[i] = random() % 0xFF;
while(true) {
err = snd_pcm_writei(handle, randomNoise, size/2);
if(err > 0) {
spdlog::info("Write {} frames", err);
} else {
spdlog::error("Error write {}\n", snd_strerror(err));
snd_pcm_recover(handle, err, 0);
continue;
}
usleep(1000); // <---- This is what causes the buffer underrun
}
}
Try to put in /etc/pulse/daemon.conf :
default-fragments = 5
default-fragment-size-msec = 2
and restart linux.
What I don't understand is why you write a buffer of size "size" to the device, and in the approximate calculations of time you rely on the "periodSize" declared by you. Then write a buffer with the size "periodSize" to the device.

How can I increase the 8 kHz audio sampling rate to 16 kHz STM32

Thanks for read my topic
I tried to record the sound, I managed to record the sound at a sample rate of 8 kHz.
this is my code it works great. But I need more sample rate like 11kHz or 16 kHz, I do not know how I can increase my sample rate to this rate.i use STM32F103C8
I got this code in the source https://www.hackster.io/christopher-william-sutjiono/read-audio-amplifier-circuit-output-using-stm-32-d9acb5
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_ADC1_Init(void);
static void MX_TIM3_Init(void);
static void MX_USART1_UART_Init(void);
/* USER CODE END 0 */
#define SAMP 8000
int main(void)
{
int k;
uint8_t buf[40];
uint16_t dat[SAMP]; // store ADC value 'SAMP'variable is 8000 1 sec for store audio
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_ADC1_Init();
MX_TIM3_Init();
MX_USART1_UART_Init();
HAL_TIM_Base_Start(&htim3);
while (1)
{
for(k=0;k<SAMP;k++)
{
while((__HAL_TIM_GET_COUNTER(&htim3))<124);
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY);
dat[k] = HAL_ADC_GetValue(&hadc1); //GET ADC Value
}
// for loop to print sammples to computer screen with 1 msec pause between samples
for (k=0;k<SAMP;k++)
{
sprintf((char*)buf,"%d\r\n", dat[k]);
HAL_UART_Transmit(&huart1, buf, strlen((char*)buf), HAL_MAX_DELAY);
HAL_Delay(1);
}
HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13,GPIO_PIN_SET);
HAL_Delay(3000);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13,GPIO_PIN_RESET);
HAL_Delay(3000);
}
}
htim3.Instance = TIM3;
htim3.Init.Prescaler = 16-1;
htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
htim3.Init.Period = 125-1;
htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim3) != HAL_OK)
{
Error_Handler();
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim3, &sClockSourceConfig) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
[1]: https://www.hackster.io/christopher-william-sutjiono/read-audio-amplifier-circuit-output-using-stm-32-d9acb5
It looks like the line while((__HAL_TIM_GET_COUNTER(&htim3))<124); is defining your sample rate, reducing the magic number from 124 will increase your sample rate.
There's almost certainly a better way to do this, such as a timer triggered DMA or similar.

How to send float values from one bluetooth module to other(HC 05)

I am doing a project where I need to send data from ultrasonic sensor wirelessly present in one arduino to other arduino where I need these values in Serial monitor. But the problem is I cannot able to send these values through bluetooth. I tried to send one character, it is appearing in serial monitor.. But when I tried to the same for integer values it is not appearing in serial monitor.
I have configured Master and Slave modes for the Bluetooth. I have uploaded the image of the code which I am using to send these values. Please help me on this. Thanks in advance .
code
//# transmitting end
#define trigPin 12
#define echoPin 11
void setup() {
Serial.begin(38400); // Default communication rate of the Bluetooth module
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
}
void loop() {
long duration;
float distance;
digitalWrite(trigPin, LOW); // Added this line
delayMicroseconds(2); // Added this line
digitalWrite(trigPin, HIGH);
delayMicroseconds(10); // Added this line
digitalWrite(trigPin, LOW);
duration = pulseIn(echoPin, HIGH);
distance = (duration/2) / 29.1;
Serial.println(distance,2); // Sends floatValue
delay(500);
}
//# receving end
#include <SoftwareSerial.h>
#define led 13
SoftwareSerial BTSerial(10, 11);
int data=0;
void setup() {
pinMode(led,OUTPUT);
Serial.begin(38400);
BTSerial.begin(38400); // Default communication rate of the Bluetooth module
}
void loop() {
int number;
if(Serial.available() > 0){ // Checks data is from the serial port
data = BTSerial.read(); // Reads the data from the serial port
//analogWrite(led,data);
delay(10);
//Serial.println(data);
}
Serial.println(data);
}
I need integer values at the serial monitor. But there I am getting some symbols like ?/<>..
From the Arduino reference, Serial.read() only reads the first available byte available in the Serial buffer. As an int is coded on 8 bytes, I would say that you need to read the incoming bytes sequentially in order to get the full value.
Maybe you can implement this by putting (Serial.available() > 0) in a while loop, concatenate the values you get in a char[8] for instance and then convert this char to a integer value.
Also, beware that you are sending floats and not int.
Thanks for the help..!
I modified the code in the receiver end to get the float values from the transmitter.. Here is my modified code
#include <SoftwareSerial.h>
int bluetoothTx = 10;
int bluetoothRx = 11;
String content; //content buffer to concatenate characters
char character; //To store single character
SoftwareSerial bluetooth(bluetoothTx, bluetoothRx);
void setup(){
bluetooth.begin(38400);
Serial.begin(9600);
}
void loop(){
bluetooth();
}
void bluetooth(){ //
while(bluetooth.available()){
character = bluetooth.read();
content.concat(character);
if(character == '\r'){ // find if there is carriage return
Serial.print(content); //display content (Use baud rate 9600)
content = ""; //clear buffer
Serial.println();
}
}
}

ESP8266 / Arduino modbus RTU Buffer data conversion

I am using ESP8266 and ModbusMaster.h library to communicate with RS485 enabled power meter. Communication works fine but responses are the ones are confusing me and I can not get correct values. My power meter shows 1.49 kWh but response from Modbus is 16318. Here is my code:
#include <ArduinoOTA.h>
#include <BlynkSimpleEsp8266.h>
#include <SimpleTimer.h>
#include <ModbusMaster.h>
#include <ESP8266WiFi.h>
/*
Debug. Change to 0 when you are finished debugging.
*/
const int debug = 1;
#define ARRAY_SIZE(A) (sizeof(A) / sizeof((A)[0]))
int timerTask1, timerTask2, timerTask3;
float battBhargeCurrent, bvoltage, ctemp, btemp, bremaining, lpower, lcurrent, pvvoltage, pvcurrent, pvpower;
float stats_today_pv_volt_min, stats_today_pv_volt_max;
uint8_t result;
// this is to check if we can write since rs485 is half duplex
bool rs485DataReceived = true;
float data[100];
ModbusMaster node;
SimpleTimer timer;
// tracer requires no handshaking
void preTransmission() {}
void postTransmission() {}
// a list of the regisities to query in order
typedef void (*RegistryList[])();
RegistryList Registries = {
AddressRegistry_0001 // samo potrosnju
};
// keep log of where we are
uint8_t currentRegistryNumber = 0;
// function to switch to next registry
void nextRegistryNumber() {
currentRegistryNumber = (currentRegistryNumber + 1) % ARRAY_SIZE( Registries);
}
void setup()
{
// Serial.begin(115200);
Serial.begin(9600, SERIAL_8E1); //, SERIAL_8E1
// Modbus slave ID 1
node.begin(1, Serial);
node.preTransmission(preTransmission);
node.postTransmission(postTransmission);
// WiFi.mode(WIFI_STA);
while (Blynk.connect() == false) {}
ArduinoOTA.setHostname(OTA_HOSTNAME);
ArduinoOTA.begin();
timerTask1 = timer.setInterval(9000, updateBlynk);
timerTask2 = timer.setInterval(9000, doRegistryNumber);
timerTask3 = timer.setInterval(9000, nextRegistryNumber);
}
// --------------------------------------------------------------------------------
void doRegistryNumber() {
Registries[currentRegistryNumber]();
}
void AddressRegistry_0001() {
uint8_t j;
uint16_t dataval[2];
result = node.readHoldingRegisters(0x00, 2);
if (result == node.ku8MBSuccess)
{
for (j = 0; j < 2; j++) // set to 0,1 for two
datablocks
{
dataval[j] = node.getResponseBuffer(j);
}
terminal.println("---------- Show power---------");
terminal.println("kWh: ");
terminal.println(dataval[0]);
terminal.println("crc: ");
terminal.println(dataval[1]);
terminal.println("-----------------------");
terminal.flush();
node.clearResponseBuffer();
node.clearTransmitBuffer();
} else {
rs485DataReceived = false;
}
}
void loop()
{
Blynk.run();
// ArduinoOTA.handle();
timer.run();
}
I have tried similar thing but with Raspberry Pi and USB-RS485 and it works.
Sample of NodeJS code is below. It looks similar to Arduino code.
// create an empty modbus client
var ModbusRTU = require("modbus-serial");
var client = new ModbusRTU();
// open connection to a serial port
client.connectRTUBuffered("/dev/ttyUSB0", { baudRate: 9600, parity: 'even' }, read);
function write() {
client.setID(1);
// write the values 0, 0xffff to registers starting at address 5
// on device number 1.
client.writeRegisters(5, [0 , 0xffff])
.then(read);
}
function read() {
// read the 2 registers starting at address 5
// on device number 1.
console.log("Ocitavanje registra 0000: ");
client.readHoldingRegisters(0000, 12)
.then(function(d) {
var floatA = d.buffer.readFloatBE(0);
// var floatB = d.buffer.readFloatBE(4);
// var floatC = d.buffer.readFloatBE(8);
// console.log("Receive:", floatA, floatB, floatC); })
console.log("Potrosnja u kWh: ", floatA); })
.catch(function(e) {
console.log(e.message); })
.then(close);
}
function close() {
client.close();
}
This code displays 1.493748298302 in console.
How can I implement this var floatA = d.buffer.readFloatBE(0); in Arduino? Looks like that readFloatBE(0) does the trick, but available only in NodeJS / javascript.
Here i part of datasheet for my device
Here is what I am getting as result from original software that came with device:
If someone could point me in better direction I would be thenkfull.
UPDATE:
I found ShortBus Modbus Scanner software and tested readings.
Library read result as Unsigned integer, but need Floating Point and Word Order swapped. It is shown on image below.
Can someone tell how to set proper conversion please.
Right, so indeed the issue is with the part done by var floatA = d.buffer.readFloatBE(0);Modbus returns an array of bytes, and the client has to interpret those bytes, ideally done by the library you're using, but if not available on Arduino, you may try manually with byte decoding functions, with the following considerattions:
Modbus registers are 16 bit in length, so length 1 = 16 bits, length
2 = 32 bits, hence the data type noted on the docs as float32 means
"2 registers used for this value, interpret as float".
Therefore, on client.readHoldingRegisters(0000, 12)you're asking to read the register with address 00, and size 12... so this makes no sense, you only need 2 registers.
On your sample Node code, first you're writing
2 registers to address 5 in client.writeRegisters(5, [0 , 0xffff])
register 5 = 0, and register 6 = 0xFFFF, why? Then you go and read
from address 0, in read(), which is the address for Total KwH per
your docs.
So, you should get an array of bytes, and you need to
decode them as a float. Modbus is Big Endian for words and bytes, so
you need to use those in the decoding functions. I don't know exactly
what is available in Arduino, but hopefully you can figure it out
with this extra info.
I suppose that if you just send the buffer to print, you'll get an integer interpretation of the value, hence the problem

Use Arduino for reading accelerometer data & save to raspi

I want to use Arduino to read data from ADXL345 accelerometer and use raspberry pi with Processing to save the data into a txt file in pi. I used the code from https://www.researchgate.net/post/How_can_I_save_data_directly_in_the_pc_using_an_Arduino_UNO
And my Arduino code is shown as follows:
#include <Wire.h>
#define DEVICE (0x53) //ADXL345 device address
#define TO_READ (6) //num of bytes we are going to read each time (two bytes for each axis)
byte buff[TO_READ] ; //6 bytes buffer for saving data read from the device
char str[512]; //string buffer to transform data before sending it to the serial port
void setup()
{
Wire.begin(); // join i2c bus (address optional for master)
Serial.begin(9600); // start serial for output
//Turning on the ADXL345
writeTo(DEVICE, 0x2D, 0);
writeTo(DEVICE, 0x2D, 16);
writeTo(DEVICE, 0x2D, 8);
}
void loop()
{
int regAddress = 0x32; //first axis-acceleration-data register on the ADXL345
int x, y, z;
readFrom(DEVICE, regAddress, TO_READ, buff); //read the acceleration data from the ADXL345
//each axis reading comes in 10 bit resolution, ie 2 bytes. Least Significat Byte first!!
//thus we are converting both bytes in to one int
x = (((int)buff[1]) << 8) | buff[0];
y = (((int)buff[3])<< 8) | buff[2];
z = (((int)buff[5]) << 8) | buff[4];
//we send the x y z values as a string to the serial port
sprintf(str, "%d %d %d", x, y, z);
Serial.print(str);
Serial.write(10);
//It appears that delay is needed in order not to clog the port
delay(15);
}
void writeTo(int device, byte address, byte val) {
Wire.beginTransmission(device); //start transmission to device
Wire.write(address); // send register address
Wire.write(val); // send value to write
Wire.endTransmission(); //end transmission
}
void readFrom(int device, byte address, int num, byte buff[]) {
Wire.beginTransmission(device); //start transmission to device
Wire.write(address); //sends address to read from
Wire.endTransmission(); //end transmission
Wire.beginTransmission(device); //start transmission to device (initiate again)
Wire.requestFrom(device, num); // request 6 bytes from device
int i = 0;
while(Wire.available()) //device may send less than requested (abnormal)
{
buff[i] = Wire.read(); // receive a byte
i++;
}
Wire.endTransmission(); //end transmission
}
Processing code is shown as follows:
import processing.serial.*;
Serial mySerial;
PrintWriter output;
void setup() {
mySerial = new Serial( this, Serial.list()[0], 9600 );
output = createWriter( "/home/pi/data.txt" );
}
void draw() {
if (mySerial.available() > 0 ) {
String value = mySerial.readString();
if ( value != null ) {
output.println( value );
}
}
}
void keyPressed() {
output.flush(); // Writes the remaining data to the file
output.close(); // Finishes the file
exit(); // Stops the program
}
When only use serial monitor window to show x, y, z values, it looks well, but when using Processing to get data while Arduino serial monitor window is running, the data format changes, e.x. wrong format
Please help me.

Resources