I'm currently working on an EEG system using the Arduino. The purpose of the system is to vibrate a vibrator for .1 seconds, wait .5 seconds, and then vibrate again for .1 seconds. However from the start I want it to read the EEG (Serial.println(brain.readCSV()); Serial.println(brain.readErrors());) every .1 seconds from the start.
The problem is that it only takes one sample and just repeats it throughout the process until it cycles, instead of continuously updating through the loop.
How can I get it to continuously read the new data while the entire system is operating.
#include "Brain.h"
#include <SPI.h>
#include <Wire.h>
int n=0;
int m=0;
// Set up the brain parser, pass it the hardware serial object you want to listen on.
Brain brain(Serial);
int vib = 5;
void setup() {
// Start the hardware serial.
Serial.begin(9600);
pinMode(vib, OUTPUT);
}
void loop() {
// Expect packets about once per second.
// The .readCSV() function returns a string (well, char*) listing the most recent brain data, in the following format:
// "signal strength, attention, meditation, delta, theta, low alpha, high alpha, low beta, high beta, low gamma, high gamma"
if (brain.update()) {
Serial.println(brain.readCSV());
Serial.println(brain.readErrors());
if(brain.readSignalQuality() == 0) {
// Vibrate
digitalWrite(vib,HIGH);
Serial.println(brain.readCSV());
Serial.println(brain.readErrors());
delay(100);
while (n<500){
n=n+100;
digitalWrite(vib,LOW);
Serial.println(brain.readCSV());
Serial.println(brain.readErrors());
Serial.println(n);
delay(100);
}
digitalWrite(vib,HIGH);
Serial.println(brain.readCSV());
Serial.println(brain.readErrors());
delay(100);
while (m<10000){
m=m+100;
digitalWrite(vib,LOW);
Serial.println(brain.readCSV());
Serial.println(brain.readErrors());
Serial.println(m);
delay(100);
}
n=0;
m=0;
}
}
}
As Delta_G says in the comments, you need to be calling brain.update() each time you want new data. Looking at the source code for Brain.cpp, notice that "readErrors" just returns a variable that only changes after you run update() (and readCSV runs sprintf on a bunch of variables that also get updated in update()). This implies that readErrors and readCSV don't actually pull new data.
Related
I am working on a small project for measuring input square wave frequency using Arduino, I did it using both timer and hardware interrupts and here is my code:
#include <TimerOne.h>
long count1=0,freq1=0;
void setup(){
attachInterrupt(5,count,RISING);
Timer1.initialize(1000000); //increments count for 1 sec and prints out count
Timer1.attachInterrupt( freq ); // attach the service routine here
Serial.begin(9600);
}
void loop(){
while(freq1)
Serial.println(freq1);
}
void count()
{
count1++;
}
void freq(){
freq1 = count1;
count1=0;
}
The problem is that output value is almost double the input frequency,
I don't know what's wrong with it. I learned about interrupts after an intensive Google search. Seems it didn't work.
There is a working example here.
It uses native ISR functions (faster) instead of arduino interrupt handlers.
Uses Timer1 for best resolution and precision.
The code is big but the part that interests you is:
The "// Setup Timer1 for precise timing" portion of void setup()
ISR(TIMER1_OVF_vect) -> for timer1 overflow counter
ISR(INT0_vect) // External Interrupt pin 2 [D2]
void PulseCaptureScheduler_callback() // Starts a capture and flags a timeout
void PrintInfoScheduler_callback() // Processes the results
I have an Arduino Uno set up to sense the light level and draw to a text file via Processing when it gets dark. I'd like to modify the Processing code to interrupt the draw loop for five seconds and then restart the draw loop. This will continuously write and overwrite the .txt file but that's not important right now.
The purpose of this excercise is to understand how to insert a break into the endless draw loop. I'm still very much a newbie to programming and am trying to wrap my head around how commands interact with eath other. Can anyone help me understand how to make this work? Eample code would be great but I'd also be happy with a conceptual description of how it's supposed to work...learn by doing and all.
I've tried putting the void draw() loop within a void loop() but it erred out. Am I on the right path?
<setup...mySerial and createWriter to path/file.txt>{
}
void draw() { //this is what needs to terminate & restart
if (mySerial.available() > 0 ) {
String value = mySerial.readString();
if ( value != null ) {
output.println( value );
}
}
}
void keyPressed and end
I believe what you're looking for is called a "state machine".
Make a variable that you can use to store a time value, then compare that to the current time to see if 5s have passed.
uint32_t last_trigger = 0; // millis() returns an unsigned, 32-bit integer
void setup()
{
Serial.begin(9600);
}
void loop()
{
if (millis() - last_trigger > 5000) { // 5000 milliseconds
last_trigger = millis(); // update last_trigger
Serial.print("last triggered at "); // report findings
Serial.print(last_trigger);
Serial.println(" milliseconds");
}
}
http://www.arduino.cc/en/Reference/Millis
If you aren't worried about really tight timing, the easy solution is to use the delay function. http://www.arduino.cc/en/Reference/Delay
The following might be a simple sketch that would do what you want. Adjust it as needed.
void setup()
{
Serial.begin(9600); // initialize serial routines
}
void loop()
{
int a = analogRead(0); // read the value of lightness
Serial.println(a); // tell processing what the value is
delay(5000); // wait for a 5 seconds
}
I am using an Arduino uno to measure the speed of a dc motor.
I have a opto sensor that gives a pulse when the motor has made a full turn.
The problem I've got starts when the motor has a speed > 90Hz.
As soon as I reach 90Hz, the Arduino doesn't enter the interrupt function.
My code:
int pin = 13;
volatile int state = LOW;
volatile unsigned long startTijd = 0;
volatile unsigned long eindTijd = 0;
unsigned int frequentie = 0;
volatile int count = 0;
void setup()
{
pinMode(pin, OUTPUT);
attachInterrupt(0, blink, FALLING); //LOW, HIGH, FALLING, RISING, CHANGE
Serial.begin(19200);
}
void loop()
{
noInterrupts();
digitalWrite(pin, state);
interrupts();
}
void blink()
{
if (count == 0) {
startTijd = micros();
}
count++;
if (count == 31) {
count = 0;
eindTijd = micros();
eindTijd -= startTijd;
Serial.print(eindTijd);
Serial.print(" ms. - ");
frequentie = 30 * 1000000 / eindTijd;
Serial.print(frequentie);
Serial.println(" Hz.");
}
state = !state;
}
My question is : When the Arduino receives interrupts at 90Hz, it doesn't execute the code in the interrupt. When the motor goes below 90Hz after that, the code works again. What am I doing wrong ?
It looks as though blink is your ISR. If that's the case, you shouldn't be doing debug I/O within that routine for 2 reasons. The first is that you are calling a process that could block. The second is that ISRs should do their thing and finish (should be highly efficient). My guess is that if you remove the debug I/O from your ISR and pass info back to the interrupted task instead (safely, of course) you will be able to service interrupts at greater than 90 hz.
Just to add to #Bruce answer. You are using serial IO in the interrupt. Each time you are printing around 15-20 characters (depending on the values calculated). Each character is encoded by 8 bit data + 1 start bit + 1 stop bit = 10 bits. So, say 20*10=200 bits. The baud rate is 19200bps, so time required to transmit 200 bits is 200/19200 sec, or in terms of frequency 19200/200=96Hz. So this is the maximum frequency achievable for transmission of 20 characters, which is close to your measured 90Hz (take in account that I am not considering any time spacing overhead between the transmits).
I have the following code:
#include <ros.h>
#include <ros/time.h>
#include <sensor_msgs/Range.h>
#define sensNumber 3
#define firstTrigPin 3
#define firstEchoPin 9
ros::NodeHandle nh;
sensor_msgs::Range range_msg;
ros::Publisher pub_range( "/ultrasound", &range_msg);
char frameid[] = "/ultrasound";
int trigPin=firstTrigPin;
int echoPin=firstEchoPin;
void increasepins(){
trigPin++;
echoPin++;
if(trigPin>firstTrigPin+sensNumber){
trigPin=firstTrigPin;
}
if(echoPin>firstEchoPin+sensNumber){
echoPin=firstEchoPin;
}
}
void setup(){
nh.initNode();
nh.advertise(pub_range);
for(int i=0;i<sensNumber;i++){
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
increasepins();
}
range_msg.radiation_type = sensor_msgs::Range::ULTRASOUND;
range_msg.header.frame_id = frameid;
range_msg.field_of_view = 0.1;
range_msg.min_range = 0.0;
range_msg.max_range = 6.47;
}
long range_time;
void loop()
{
increasepins();
//publish the adc value every 50 milliseconds
//since it takes that long for the sensor to stablize
long duration, distance;
digitalWrite(trigPin, LOW); // should be high?
delayMicroseconds(2); // make this 20
digitalWrite(trigPin, HIGH);
delayMicroseconds(10); // reset value?
digitalWrite(trigPin, LOW);
distance = pulseIn(echoPin, HIGH)/ 58,2; //sensor constant is 3.4
range_msg.range = distance;
range_msg.header.stamp = nh.now();
range_time = millis() + 50;
range_msg.field_of_view = trigPin;
range_msg.min_range = echoPin;
pub_range.publish(&range_msg);
nh.spinOnce();
}
This above code runs at my funduino at aprox 2 times a second for the whole loop. If I however remove the increasePins method it runs at around 100 times per second. Why the big chance? It seems like such a trivial piece of code (just increase 2 variables and then compare them) make such a large difference?
For reference we are talking about this function:
void increasepins(){
trigPin++;
echoPin++;
if(trigPin>firstTrigPin+sensNumber){
trigPin=firstTrigPin;
}
if(echoPin>firstEchoPin+sensNumber){
echoPin=firstEchoPin;
}
}
Which to me looks really simple when compared to having to wait for the echo to come back and getting the time and that sort of things required for the rest of the code.
I believe that one of the problem is that if you comment the increasePins function in the loop, the compiler will decide to take some of the logic outside the loop. For that you need to look # the assembly code and see what's being done inside the loop.
Another problem may be related to the pin behavior. For example, I read that "pulseIn" function sends a pulse to the pin and measures it's duration. You use it to pulse the "echoPin". I suspect that if you don't change the echoPin you will have a rather constant duration. However, changing the echoPin may lead to a situation where another pin's pulse duration would be longer. To test this, you can try and use pulsePin(echoPin, HIGH, timeout) with a timeout parameter for the case when you did not comment the increasePins function. I expect the loop to run faster.
So i think that the increasePins is not a bottleneck. I recommend making it inline however (could add some speedup if the compiler hasn't done this already).
I'm using this code :
int trigPin = 7;
int echoPin = 8;
void setup() {
Serial.begin(9600);
pinMode(trigPin,OUTPUT);
pinMode(echoPin,INPUT);
}
void loop() {
int duration;
int distance;
digitalWrite(trigPin,HIGH);
delayMicroseconds(1000);
digitalWrite(trigPin,LOW);
duration = pulseIn (echoPin,HIGH);
distance = (duration/2)/29.1;
Serial.print("distance = ");
Serial.println (distance);
delay(500);
}
I understand the concept that we send a pulse of 1000 µsec in this case and we wait for the reflected signal. But I don't understand how in this code, only the pulse width of the reflected signal is being used for the calculation.
I searched around and they say the reflected pulse width is proportional to the distance traveled. Can someone please explain how this happens (the physics behind it) and also where does the 29.1 comes from?
I read this documentation but I still don't understand the pulse width concept.
Many thanks in advance!
Like Chris touched on in the comments, the input pin goes HIGH for the time between it being send and received. I'm not exactly sure if it goes HIGH for a certain amount of time after or during the transmission, but you might be able to find that on a datasheet.
where does the 29.1 come from?
That's the speed of sound through air... you can use that to convert the time to centimeters. You'll have to divide it by two because it goes two ways.
Recap:
Arduino sends pulse to SR04 (1000 microseconds):
digitalWrite(trigPin,HIGH);, delayMicroseconds(1000);, &digitalWrite(trigPin,LOW);.
SR04 emits a ping and changes the signal pin to HIGH
The ping hits an object, bounces back, and goes back to the SR04
The SR04 sets the pin back to LOW
The Arduino measures the length the signal pin is HIGH with this:
duration = pulseIn (echoPin,HIGH);