I want to compare changing values (which I declare in a look up table, not shown in the following example) with timer 0 (TCNT0) of the Arduino.
The results from an oszi showing me, that I don't get what I want to. So I've tried to see the timer values (obviously I was expecting to see values from 0-255). But serial monitor shows me, that I only get values with a big gap between each other.
My question is: is the serial monitor just too slow to show all the values, or is my approach wrong?
int PIN11 = 11;
void setup()
{
Serial.begin(9600);
pinMode(PIN11, OUTPUT);
}
void loop()
{
if(TCNT0 < 100)
{
digitalWrite(PIN11, HIGH);
}
else
{
digitalWrite(PIN11, LOW);
}
Serial.println(TCNT0);
}
Serial monitor returns following output:
Expected values: 0 1 2 3... Actual values: 14 30 46 62 78 94 110
130 150 170 190 210 230 250 14 ...
Yes, your UART is too slow.
Your mainloop is running as fast as it could and don't wait for the UART to be ready. Just wait after the Serial.println(TCNT0); until its ready. Or put a small delay (approx 1ms) after Serial.println(TCNT0);
But if if you want to see your expected values just increment an integer value in your loop and send it to the UART. Don't to that with a timer value.
Related
I was trying to read infra red signal from arduino so I wrote this code
{
long int initial = micros();
int timeinms = millis();
int oldValue = 0;
int bitPosition = 0;
while(millis() - timeinms< 100){
int value = (PIND & B10000000 ) >> 7;
if(value != oldValue){
oldValue = value;
arr[bitPosition] = micros() > initial ? micros() - initial : 4294967295 - initial + micros();
bitVal[bitPosition] = value;
bitPosition++;
}
}
}
But when I read signal I get the general timing is correct 430 and 600 instead of 562 and 1620 instead of 562 * 3 but why is there such difference. I know micros has 4 microseconds error but this should result to at most 8 microseconds error not 80 or 100
So what is the problem is it a bug in the code or something I am missing
Tried above code getting times with + or - 80 microseconds to 100
You don't know how millis is working in background. Your code is interrupted every 1 millisecond by timer. I guess that duration of ISR is explanation of observed differentiae of time measurement. Don't use millis you get more precise time measurement. Or use other timer in capture mode for most precise measurement.
I have tried to write wireless servo control using two arduino nano v3 boards and two bluetooth 4.0 modules. First code is transmitter. It's very simple. It reads PPM signals and transform to separates PWM values for each channel. I use hardware serial port.
#include <PPMReader.h>
#include <InterruptHandler.h>
int ppmInputPin = 3;
int channelAmount = 2;
PPMReader ppm(ppmInputPin, channelAmount);
void setup()
{
Serial.begin(9600);
Serial.write("AT\r\n");
delay(10);
Serial.write("AT\r\n");
Serial.write("AT+INQ\r\n");
delay(5000);
Serial.write("AT+CONN1\r\n");
}
void loop()
{
unsigned long value1 = ppm.latestValidChannelValue(1, 0);
Serial.println(value1);
}
Receiver is simple too. It reads values from bluetooth and parse into integer value and sends to servo by 7th pin. Again I have used hardware serial port.
#include <Servo.h>
int PWM_OUTPUT = 7;
Servo servo;
void setup() {
servo.attach(PWM_OUTPUT);
Serial.begin(9600);
}
void loop() {
int pwmValue = Serial.parseInt();
if (Serial.available()) {
if(pwmValue > 900 && pwmValue < 2001) {
servo.writeMicroseconds(pwmValue);
}
}
}
All it works. But it has delay around 2-3 seconds. Can be problem in "spamming" serial port?
The first thing you need to ask yourself when implementing a device-to-device communication is how fast should I be sending? and if I send at that rate: is the receiver going to be able to keep pace (reading, doing processing or whatever it needs to do and answer back)?
This is obviously not about the baud rate but about what your loops are doing. You are using two different libraries: PPMReader and Servo. Now, pay attention to what each device is doing in their respective loops:
//Sending
void loop() {
unsigned long value1 = ppm.latestValidChannelValue(1, 0);
Serial.println(value1);
}
//Receiving
void loop() {
int pwmValue = Serial.parseInt();
if(pwmValue > 900 && pwmValue < 2001) {
servo.writeMicroseconds(pwmValue);
}
}
I don't really know how long it takes to execute each line of code (take a look here for some comments on that) but you cannot seriously expect both loops to magically synchronize themselves. Considering they are doing very different things (leaving out the serial part) dealing with different hardware, I would expect one of them to take significantly longer than the other. Think about what happens if that's the case.
As I said, I have no idea how long it takes to call ppm.latestValidChannelValue(1, 0) but for the sake of my argument let's say it takes 0.1 milliseconds. To have an estimate of the time it takes to complete one iteration around the loop you need to add the time it takes to print one (or two) bytes to the port with Serial.println(value1) but that's easier, maybe around 20-100 microseconds is a good ballpark figure. With these estimates, you end up reading 5000 times per second. If you are not happy or you don't trust my estimates I would suggest you do your own tests with a counter or a timer. If you do the same exercise for the other side of the link and let's say you get it's twice as fast, it runs 10000 times per second, how do you think it would happen with the communication? Yes, that's right: it will get clogged and run at snail pace.
Here you should carefully consider if you really need that many readings (you did not elaborate on what you're actually doing so I have no idea, but I lean on thinking you don't). If you don't, just add a delay on the sender's side to slow it down to a reasonable (maybe 10-20 iterations per second) speed.
There are other things to improve on your code: you should check you have received data in the buffer before reading it (not after). And you need to be careful with Serial.parseInt(), which sometimes leads to unexpected results but this answer is already too long and I don't want to extend it even more.
I found problem. It was in serial port spamming. I have added check if current value is not equal with previous value and it have started work and next small issue was in receiver. I read value before it was available.
#include <PPMReader.h>
#include <InterruptHandler.h>
int ppmInputPin = 3;
int channelAmount = 2;
PPMReader ppm(ppmInputPin, channelAmount);
volatile unsigned long previousValue1 = 0;
void setup()
{
Serial.begin(9600);
Serial.write("AT\r\n");
delay(10);
Serial.write("AT\r\n");
Serial.write("AT+INQ\r\n");
delay(5000);
Serial.write("AT+CONN1\r\n");
Serial.println("Transmitter started");
}
void loop()
{
unsigned long value1 = ppm.latestValidChannelValue(1, 0);
if(previousValue1 != value1) {
previousValue1 = value1;
Serial.println(value1);
}
}
I'm trying to write a simple program (as a pre-cursor to a more complicated one) that stores an array of bytes to progmem, and then reads and prints the array. I've looked through a million blog/forums posts online and think I'm doing everything fine, but I'm still getting utter gibberish as output.
Here is my code, any help would be much appreciated!
void setup() {
byte hello[10] PROGMEM = {1,2,3,4,5,6,7,8,9,10};
byte buffer[10];
Serial.begin(9600);
memcpy_P(buffer, (char*)pgm_read_byte(&hello), 10);
for(int i=0;i<10;i++){
//buffer[i] = pgm_read_byte(&(hello[i])); //output is wrong even if i use this
Serial.println(buffer[i]);
}
}
void loop() {
}
If I use memcpy, I get the output:
148
93
0
12
148
93
0
12
148
93
And if I use the buffer = .... statement in the for loop (instead of memcpy):
49
5
9
240
108
192
138
173
155
173
You're thinking about two magnitudes too complicated.
memcpy_P wants a source pointer, a destination pointer and a byte count. And the PROGMEM pointer is simply the array. So, your memcpy_P line should like like
memcpy_P (buffer, hello, 10);
that's it.
memcpy (without the "P") will not be able to reach program memory and copy stuff from data RAM instead. That is not what you want.
to enter context I'm doing this:
Drive a stepper motor through the variation of pulse frequency input to a Driver (A4988) (It is not necessary to know the functioning of this for this question). Now and got varying the frequency of the pulses (They change the engine speed). You need to know that for the motor shaft 1 full turn have to get 200 pulses (The engine is 1.8 ° degrees per step).
I got the engine and make him a full turn in 1 second.
Period = 0.005s
To program this I am using the component: TimerUnit_LDD.
With a frequency of 163840 Hz count
In the case of the whole turn 1 to get that frequently use this function.
---- main.c
TU1_Enable (TU1_DeviceData);
TU1_SetPeriodTicks (TU1_DeviceData, 410);
The parameter 410 is compared to the period I want, as is sending pulses programmed by changing the value of a pin taken into account both the high and the low pulse, like this:
----- Events.c
TU1_OnCounterRestart void (* UserDataPtr LDD_TUserData)
{
Step1_NegVal ();
}
The period for serious formulates 819.2, having in mind the above serious approximates 409.6 and 410 (seen in a oscilloscope frequency is 200 Hz (ok).
Already entered in context the problem is this:
---- main.c
TU1_Enable (TU1_DeviceData); // Enable the counter
TU1_SetPeriodTicks (TU1_DeviceData, 410); // Setting the desired period
for (;;) {
TU1_Enable (TU1_DeviceData);
WAIT1_Waitms (1000); // Rotation time
TU1_Enable (TU1_DeviceData); // Disable the counter
}
With this code is what I try to check that the frequency calculation was correct and that in one second would 1 turn. But what happens is that it gives the rotation but is offset a little more. I guess this goes through the runtime required for each line of code.
What I want to know is, how could obtain the numerical value of a variable in an event? how could I do something like this.
---- main.c
TU1_Enable (TU1_DeviceData); // Initialize the counter
TU1_SetPeriodTicks (TU1_DeviceData, 410); // Setting the desired period
for (;;) {
for (;;) {
if (GetValue (x) == 200) break; // GetValue (x) This function is what I want to achieve
}
WAIT1_Waitms (1000);
}
----- Events.c
TU1_OnCounterRestart void (* UserDataPtr LDD_TUserData)
{
Step1_NegVal ();
x = x + 1;
}
GetValue (x) this function would obtain the value of x which is in Events.c and define a number of pulses to control espefico.
Take a variable and is affected by the counter, and that this gets to 200 (for 1 turn in 1 second).
This would have the certainty that menera be sent alone and lonely, neither more nor less, only 200 pulses.
I require this as specific as I am desarrolando the program for a CNC machine and is too importanto precision is the highest.
I hope you understand and I speak Spanish and this was translated by Chrome
Programmed in C language,
Freescale KL25Z,
CodeWarrior,
OPEN_SDA,
I managed to implement something but I think it may be easier to get
-----(main.c)
extern int count;//called external variable
int main(void){
PE_low_level_init();
TU1_Enable(TU1_DeviceData);
TU1_SetPeriodTicks(TU1_DeviceData,410);//T=0.005 sec
for(;;){
Term1_Cls();// Clear Console
WAIT1_Waitms(1000);
Term1_MoveTo(0,0);// Set 0,0 in Console
for(;;){
TU1_Enable(TU1_DeviceData);
Term1_SendNum(count);
Term1_CRLF();
if (count>400){//amount of high and low pulse counting
count=0;
TU1_Disable(TU1_DeviceData);
break;
}
}
WAIT1_Waitms(1000);
Dir1_NegVal();
}
----(Events.c)
int count;
void TU1_OnCounterRestart(LDD_TUserData *UserDataPtr)
{
Step1_NegVal();
count=count+1; //counter
}
I'm trying to send a value to my Arduino Nano via USB using the terminal.
However: when using Serial.print() in the loop to print out the value of the read byte I get three separate values - none of them the value I actually sent.
For example: When sending 41 I get 52, 49 and 13 printed in the terminal.
My code looks like this:
byte incomingByte;
void setup() {
Serial.begin(9600);
}
void loop() {
if (Serial.available() > 0) {
incomingByte = Serial.read();
Serial.print(incomingByte);
}
}
Any idea what I'm doing wrong?
Your terminal is printing things out in decimal and sending in ASCII. If you take a look at an ASCII table, 52, 49, and 13 correspond to 41\r in ASCII. You typed 4 as ASCII and got decimal 52 back, then 1 in ASCII and got decimal 49 back and probably hit Enter or Carriage Return (CR - \r) and got decimal 13 back.
http://www.asciitable.com/