STM32L476 on Nucleo, can't run at 80 Mhz - stm32

I am running the following code on a fresh & blank new project for my Nucleo-L476RG board:
GPIOA->BSRR = GPIO_PIN_4;
GPIOA->BRR = GPIO_PIN_4;
The clock config is default and as follow:
I am expecting to see on my oscilloscope a 80 Mhz clock but I only see 10 Mhz.
When I enable "Master Clock Output" I can see the 80 Mhz BUT my code does not seem to run at that speed.
Any idea what might cause this?

I am expecting to see on my oscilloscope a 80 Mhz clock but I only see
10 Mhz.
Why do you expect that those two C stateements will execute in one CPU clock? Do you think it is possible? Of course it is not
it is translated to
str r2, [r3]
str r2, [r3, #4]
str instruction takes 2 clocks. two of them 4 clocks. If you run from the FLASH you need to add wait states. So this will take about 8 clocks - and you see 10MHz. You can try to run from the SRAM them it will be faster.
of course it is valid only if you have those instructions one after another
GPIOA->BSRR = GPIO_PIN_4;
GPIOA->BRR = GPIO_PIN_4;
GPIOA->BSRR = GPIO_PIN_4;
GPIOA->BRR = GPIO_PIN_4;
GPIOA->BSRR = GPIO_PIN_4;
GPIOA->BRR = GPIO_PIN_4;
GPIOA->BSRR = GPIO_PIN_4;
GPIOA->BRR = GPIO_PIN_4;
GPIOA->BSRR = GPIO_PIN_4;
GPIOA->BRR = GPIO_PIN_4;
/*...*/
When you have it in the loop the loop will add additional overhead.

Related

Synchronous Data Transfer between Arduino and Matlab Serially

I am working on a project where i read real time current signal on an Arduino using a Split Core CT. I am able to read exact AC Current and replicate it in Arduino Serial Plotter using the code below.
void setup() {
Serial.begin(115200);
}
void loop() {
Serial.println( (double)(analogRead(A5) - analogRead(A0))*0.009765625 );
}
But I have to do further calculations on it like FFT and THD, so I am sending that data to MATLAB over serial communication. Below is my Matlab Script which reads 1000 data samples, stores it in an array and performs calculations and finally plots it.
clc; close all;
if ~isempty(instrfind)
fclose(instrfind);
delete(instrfind);
end
s1=serial('COM5','Baudrate',115200);
fopen(s1);
Fs=1000;
LoS = 100;
T = 1/Fs;
t = (0:LoS-1)*T;
sig = zeros(1,LoS-1);
str='';
sen=0;
for j = 1:LoS
str=fscanf(s1);
sen=str2double(str);
sig(j)=sen;
end
subplot(2,1,1);
axis([0 LoS -4 4]);
plot(t,sig);
xlabel('Counts');
ylabel('Magnitude');
title('Signal');
Y=fft(sig);
P2 = abs(Y/LoS);
P1 = P2(1:LoS/2+1);
P1(2:end-1) = 2*P1(2:end-1);
f = Fs*(0:(LoS/2))/LoS;
subplot(2,1,2);
axis([0 100 0 10]);
plot(f,P1);
title('FFT(Signal)');
xlabel('f (Hz)');
ylabel('|Power(f)|');
fclose(s1);
delete(s1);
clear s1;
The issue is the frequency of actual signal is 60Hz, but my code outputs a peak at 31Hz. I checked the same code on matlab simulated sinusoids, it gives exact results. But on real data its miscalculating. I implemented the same logic on LABView as well the result remains 31Hz. Can anyone pinpoint my mistake? I am really stuck at this.
Thanks for your time.
You should fix the Arduino sample rate to 1000 samples per second.
As Daniel commented, the Arduino is working as fast as possible, instead of sampling at 1KHz (instead of sampling 1000 samples per second).
You can fix your Arduino loop to sample at 1KHz by making sure each iteration takes 1000 micro-seconds.
The loop below reads the time at the beginning and at the end of each iteration.
At the end of each iteration, there is a delay that completes the duration to 1000us.
void loop() {
unsigned long start_time_us, delta_time_us;
//Returns the number of microseconds since the Arduino board began running the current program
//https://www.arduino.cc/reference/en/language/functions/time/micros/
start_time_us = micros();
Serial.println( (double)(analogRead(A5) - analogRead(A0))*0.009765625 );
//Passed time in microseconds.
delta_time_us = micros() - start_time_us;
if (delta_time_us < 1000)
{
//Delay the remaining time - complete to 1000us (keep sample rate at 1000 samples per second).
//https://www.arduino.cc/reference/en/language/functions/time/delaymicroseconds/
delayMicroseconds((unsigned long)1000 - delta_time_us);
}
}
Please note: I could not verify the solution because I don't have an Arduino board (or simulator).
Remark: sending samples as text strings is inefficient, and may saturate the serial port.
I suggest you do the following:
Send binary data (using Serial.write instead of Serial.println).
Instead of converting the sample to double before sending it from Arduino, send the sample in short format (two bytes): Send the value (short)(analogRead(A5) - analogRead(A0)).
In the MATLAB side, read 1000 binary samples: sig = fread(s1, 1000, 'int16');
Perform the conversion to double and scale samples in MATLAB: sig = double(sig) * 0.009765625.
Arduino code:
//Serial.println( (double)(analogRead(A5) - analogRead(A0))*0.009765625 );
short analog_read = (short)(analogRead(A5) - analogRead(A0));
Serial.write((uint8_t*)&analog_read, 2); //Send two bytes in int16 binary format
MATLAB code:
% for j = 1:LoS
% str=fscanf(s1);
% sen=str2double(str);
% sig(j)=sen;
% end
sig = fread(s1, 1000, 'int16'); % Read 1000 analog samples (each sample is int16).
sig = double(sig) * 0.009765625; % Convert 1000 samples to physical values in double format
The above code is more efficient for both Arduino and MATLAB.
Remark: Keep in mind that I didn't test the code - it's just for demonstrating the concept.

CUDA GPU time in MATLAB increasing when the grid size is increased

I am using MATLAB R2017a. I am running a simple code to calculate cumulative sum from the first point until ith point.
my CUDA kernel code is:
__global__ void summ(const double *A, double *B, int N){
for (int i=threadIdx.x; i<N; i++){
B[i+1] = B[i] + A[i];}}
my MATLAB code is
k=parallel.gpu.CUDAKernel('summ.ptx','summ.cu');
n=10^7;
A=rand(n,1);
ans=zeros(n,1);
A1=gpuArray(A);
ans2=gpuArray(ans);
k.ThreadBlockSize = [1024,1,1];
k.GridSize = [3,1];
G = feval(k,A1,ans2,n);
G1 = gather(G);
GPU_time = toc
I am wondering why the GPU time increasing when i increase the grid size (k,.GridSize). for instant for 10^7 data,
k.GridSize=[1,1] the time is 8.0748s
k.GridSize=[2,1] the time is 8.0792s
k.GridSize=[3,1] the time is 8.0928s
From what i understand, for 10^7 number of data, the system will need 10^7 / 1024 ~ 9767 blocks, so the grid size should be [9767,1].
The GPU device is
Name: 'Tesla K20c'
Index: 1
ComputeCapability: '3.5'
SupportsDouble: 1
DriverVersion: 9.1000
ToolkitVersion: 8
MaxThreadsPerBlock: 1024
MaxShmemPerBlock: 49152
MaxThreadBlockSize: [1024 1024 64]
MaxGridSize: [2.1475e+09 65535 65535]
SIMDWidth: 32
TotalMemory: 5.2983e+09
AvailableMemory: 4.9132e+09
MultiprocessorCount: 13
ClockRateKHz: 705500
ComputeMode: 'Default'
GPUOverlapsTransfers: 1
KernelExecutionTimeout: 0
CanMapHostMemory: 1
DeviceSupported: 1
DeviceSelected: 1
thank you for your response.
You appear to be worrying about a very very small portion of the time compared to the overall effect. The real question you should be asking is: does this amount of time to solve this problem make sense? The answer to that is no absolutely not.
Here is a modified code which should run much faster
n=10^7;
dev = gpuDevice;
A = randn(n,1,'gpuArray');
B = randn(n,1,'gpuArray');
tic
G = A+cumsum(B);
wait(dev)
toc
On my 1060 this runs in 0.03 seconds. For even faster speeds you can use single precision
At any rate, that 0.02 seconds could be easily attributable to small changes in loads on your GPU. It's a much more likely scenario than having to do with gridsizes.

Reading Data from Serial Port and Plotting in Real Time

I am looking to take in data from a temperature sensor on an Arduino Uno board and have matlab store the data while also plotting the data on a graph in real time to monitor sensor changes. This will eventually be implemented with a different sensor and this more of a proof of concept. I have two issues currently troubling me:
1) I need to be gathering the data points 1000x a second (which my current code cannot do)
2) After several seconds of monitoring the data a great deal of noise enters the system
Here is my matlab code
SerialPort = 'com6';
s = serial(SerialPort, 'BaudRate', 250000, 'DataBits', 8);
fopen(s);
voltage = 0;
t = 0;
y = 1;
voltage = fscanf(s);
VoltageValue(y,1)=str2double(voltage);
h = animatedline(t,VoltageValue(y,1));
xlim([0 1000]);
ylim([100 200]);
tic
while t <= 1000
voltage = fscanf(s);
VoltageValue(y,1)=str2double(voltage);
addpoints(h, t, VoltageValue(y,1));
t= t+1;
y= y+1;
drawnow
end
toc
fclose(s);
delete(s);
clear s;
Here is my arduino code
int tmppin = 0;
void setup() {
// put your setup code here, to run once:
Serial.begin(250000);
pinMode(tmppin, INPUT);
}
void loop() {
// put your main code here, to run repeatedly:
int tempreading = analogRead(tmppin);
Serial.println(tempreading);
}
From what I have tried, the serial communication at 38400bd is enough to transmit an int at 1kHz. You can use 115200bds; your speed of 500000bds is not supported, even if it usually works.
The ADC will have no problem with 1000Hz. The Arduino command analogRead works at 10kHz; and if you would access register of atmel MCU directly, you could speed up analogRead to 100kHz.
Your code is slowed down with drawnow. You dont need to refresh at 1kHz; if you refresh at 10Hz, it will be real time for your eye.
In arduino sketch you should put a delay(1) (1ms), so you know the serial buffer wont get full.
also , to speedup the transfer speed, sending the data as binary will help a lot the Serial.println(tempreading); you used sends data as string. meaning it will send 6 characters each time. (5 characters + the CR). sending as binary will need only 2 bytes.
; a 3X speed increment already.
To send data as binary in arduino , use
serial.write(data_to_send>>8); //send most significant byte
serial.write( data_to_send && f); //send least significant byte

Incorrect UDP data reception in Matlab

My FPGA is continuously sending UDP packets on network using 10/100/1000 Mbps ethernet and i have written a MATLAB code to capture the data. FPGA kit is connected to a 1 gbps switch and then to PC.
The problem is that after a certain number of packets (around 1080000 Bytes) are received in Matlab, the next packets that are received are corrupted although the FPGA is sending correct data which i have verified by running Matlab with Wireshark.
1) Does it have something to do with the fact that the transmission rate from FPGA is high (5.18 Mbps in Wireshark) & the reception rate in Matlab is low?
2) Is it because of some internal memory issue. No more packets are received after around 1080000 Bytes worth of UDP data is received (problem shown in figure)? I tried changing the buffer_size & buffer_read_count but to no avail.
3) Is it because of the Matlab's internal buffer getting FULL? Will flushinput() command be of any help in this case if indeed the buffer is getting FULL?
I am pasting the Matlab code below.
clc
clearall
closeall
packet_size = 18; %Size of 1 Packet
buffer_size = 1000*packet_size; % Buffer to store 1000 packets each of Packet_Size
buffer_read_count = 100; %How many times the buffer must be read
do_post_processing = 1;
u=udp('192.168.0.100','RemotePort',4660,'Localport',4661);
set(u,'DatagramTerminateMode','off');
set(u, 'InputBufferSize', 3*buffer_size);
set(u,'Timeout', 10);
fopen(u);
x=tic;
ii=1;
kk = 1;
while(1)
if(u.BytesAvailable>= buffer_size)
[a, count] = fread(u, buffer_size);
data(:, kk) = a;
data_buffer_read = reshape(a, packet_size, buffer_size/packet_size);
data_start(:,kk) = (data_buffer_read(18,1:10)).';
data_end(:,kk) = (data_buffer_read(18,end-10:end)).';
kk = kk + 1;
end
if(kk == buffer_read_count + 1)
break;
end
end
fclose(u);
%delete(u);
t=toc(x);
bw = (buffer_size*buffer_read_count*8)/t;
fprintf('Achieved data rate: %e bps\n', bw);
% post processing
data_reshape = reshape (data, packet_size, buffer_size*buffer_read_count/packet_size);
if(do_post_processing==1)
plot(data_reshape.');
title('UDP Data v/s Total Packets at 10 Mbps Ethernet Link');
xlabel('Total Number of Packets');
ylabel('Packet Data');
end
A thread i posted previously provides a link to this problem.
Slow speed of UDP reception in Matlab
Please provide any guidance about this issue.
Thank you.
Regards,

Setting sampling rate in MATLAB for Arduino

I'm having trouble getting consistent results with the code I am using. I want to run my Arduino for a specific amount of time (say 20 seconds) and collect data from the analog pin with a specific sampling rate (say four samples a second). The code is as follows.
a_pin = 0;
tic;
i = 0;
while toc < 20
i = i + 1;
time(i) = toc;
v(i) = a.analogRead(a_pin);
pause(.25);
end
Is there a way to set the loop to run a specific time and then in the loop sample at a different rate?
You can try this:
a_pin = 0;
fs = 4; % sampling frequency (samplings per second)
mt = 20; % time for measurements
ind = 1;
nind = 1;
last_beep = 0;
tic;
while toc < mt
time(ind) = toc;
v(ind) = a.analogRead(a_pin);
% wait for appropriate time for next measurement
while( nind == ind )
nind = floor(toc*fs) + 1;
end
ind = nind;
% beep every second
if (ceil(toc) > last_beep)
beep(); % don't know if this one exist, check docs
last_beep = ceil(toc);
end
end
Maximal sampling time for a single Arduino analog read command is around 0.04 s, in practice I'd go minimally 0.05. Adding two read operations is in the order of 2*0.04, in practice more like 0.1 s. I think it is mainly limited by the USB communication speeds.
I am also new at arduino, but having implemented a real time analysis for EEG using it, on practice, I was able to sample 2 analog channels with a samplinf frequency between 57 and 108Hz. It was very variable (calculated through tic/toc), but it is still proper for realtime processing in my case.
My code uses a While loop, a series of memory updates, digital pin manipulations, plot of trace (drawnow) and seems to run smoothly enough
My answer is simply here : 0.0283 sec for sampling 2 analog inputs in my case.
Cheers