Go Down

Topic: Speed of a wheel measurement, light effect and sound effect (Read 944 times) previous topic - next topic

Yepino

Hello my friends

 I am going to try to explain my project first and then put my code and see if I can get some help.

 My project is to measure the speed of a bike and the lighting effect happens to different speeds of the wheel. For example if the speed is below 15mph the RGB LED will lit red and when the speed gets to over 30mph the LED will lit Green and so on, and at the same time when the speed gets to 30mph I wanted a sound to be played.

 Now in my case I was able to do the speed measurement and the lighting effect perfectly, now the problem is when I add the code for the SD card or sound, it doesn't work properly. When I combined the codes even the light only lit green which means it ain't working properly. so what I did was I tried to so make the 2nd part or the sound effect on another Arduino board and Voila the speed measurement and the lighting effect works except there is no sound playing at 30mph.

So what I think I am doing a mistake is on the I2C communication between the 2 Arduinos, I connected them like in A4 and A5 of the 2 Arduinos and common ground for both of them as well, but the code doesn't seem write. Can some body help me by directing me into a right direction please, Thanks a lot.


Code for the Master Arduino or the Speed and Lighting effect


Code: [Select]


//calculations
//tire radius ~ 10 inches
//circumference = pi*2*r =~62.8 inches
//max speed of 35mph =~ 616inches/second
//max rps =~7.25

#include <FastLED.h>
#define hallPin  2//pin connected to read switch
#define LED_PIN 7
#define NUM_LEDS 256
#include <Wire.h>

CRGB leds[NUM_LEDS];


//storage variables
float radius = 10;// tire radius (in inches)- CHANGE THIS FOR YOUR OWN BIKE
int ledpin = 3;
int hallVal;
long timer = 0;// time between one full rotation (in ms)
float mph = 0.00;
float circumference;
int x = 0;
//boolean backlight;

int maxhallCounter = 100;//min time (in ms) of one rotation (for debouncing)
int hallCounter;


void setup(){

  hallCounter = maxhallCounter;
  circumference = 2*3.14*radius;
  pinMode(LED_PIN,OUTPUT);
  pinMode(ledpin,OUTPUT);
  pinMode(hallPin, INPUT);
//  pinMode(Speaker, OUTPUT);
 
  FastLED.addLeds<WS2812, LED_PIN, GRB>(leds, NUM_LEDS);
  FastLED.setBrightness(32);
//  checkBacklight();
 
//  Serial.write(12);//clear
 
  // TIMER SETUP- the timer interrupt allows preceise timed measurements of the reed switch
  //for mor info about configuration of arduino timers see http://arduino.cc/playground/Code/Timer1
  cli();//stop interrupts

  //set timer1 interrupt at 1kHz
  TCCR1A = 0;// set entire TCCR1A register to 0
  TCCR1B = 0;// same for TCCR1B
  TCNT1  = 0;
  // set timer count for 1khz increments
  OCR1A = 1999;// = (1/1000) / ((1/(16*10^6))*8) - 1
  // turn on CTC mode
  TCCR1B |= (1 << WGM12);
  // Set CS11 bit for 8 prescaler
  TCCR1B |= (1 << CS11);   
  // enable timer compare interrupt
  TIMSK1 |= (1 << OCIE1A);
 
  sei();//allow interrupts
  //END TIMER SETUP
 
  Serial.begin(9600);
  // Start the I2C Bus as Master
  Wire.begin();
}


ISR(TIMER1_COMPA_vect) {//Interrupt at freq of 1kHz to measure reed switch
  hallVal = digitalRead(hallPin);//get val of hall sensor
  if (hallVal==LOW){//if reed switch is closed
    if (hallCounter == 0){//min time between pulses has passed
      mph = (53.8*float(circumference))/float(timer);//calculate miles per hour
      timer = 0;//reset timer
      hallCounter = maxhallCounter;//reset hallCounter
    }
    else{
      if (hallCounter > 0){//don't let reedCounter go negative
        hallCounter -= 1;//decrement reedCounter
      }
    }
  }
  else{//if reed switch is open
    if (hallCounter > 0){//don't let reedCounter go negative
      hallCounter -= 1;//decrement reedCounter
    }
  }
  if (timer > 2000){
    mph = 0;//if no new pulses from reed switch- tire is still, set mph to 0
  }
  else{
    timer += 1;//increment timer
  }
}


void loop(){
  if(hallVal == LOW){
    digitalWrite(ledpin, HIGH);
  }
  else{
    digitalWrite(ledpin, LOW);
  }
  //print mph once a second
  Serial.println(mph);
  if (mph == 0) {
    for(int i=0; i<=255; i++){
      leds[i] = CRGB(0,0,0);
    }
    FastLED.show();
  }
  if (mph <= 15 && mph>0) {
    for(int i=0; i<=255; i++){
      leds[i] = CRGB(255,0,0);
    }
    FastLED.show();
  }
  if (mph <= 30 && mph>15) {
    for(int i=0; i<=255; i++){
      leds[i] = CRGB(255,105,0);
    }
    FastLED.show();
  }
  if (mph > 30) {
    for(int i=0; i<=255; i++){
      leds[i] = CRGB(0,255,0);
    }
    FastLED.show();
  }
  int x = digitalRead(mph);
  Wire.beginTransmission(9); // transmit to device #9
  Wire.write(x);              // sends x
  Wire.endTransmission();    // stop transmitting
  x++; // Increment x
  if (x > 30) x = 0; // `reset x once it gets 30
//  delay(500);
}



And here is the code for the slave Arduino or for the sound


Code: [Select]


#include <SD.h>
#define SD_ChipSelectPin 4
#include <TMRpcm.h>
#include <SPI.h>
#define Speaker 9
#include <Wire.h>


int x = 0;
TMRpcm tmrpcm;
char mychar;

void setup() {
  // put your setup code here, to run once:


   pinMode(Speaker, OUTPUT);
// Start the I2C Bus as Slave on address 9
   Wire.begin(9);
// Attach a function to trigger when something is received.
   Wire.onReceive(receiveEvent);
 
tmrpcm.speakerPin = 9;
if(!SD.begin(SD_ChipSelectPin)){
  Serial.println("SD fail");
  return;
}
tmrpcm.setVolume(5);
}

void receiveEvent(int howMany){
  while (1 < Wire.available()){
    char c = Wire.read();
    Serial.print(c);
  }
  int x = Wire.read();  //read one character from I2C
  Serial.println(x);
}

void loop() {
  // put your main code here, to run repeatedly:
if (x == 30){
  digitalWrite(Speaker, HIGH);
  tmrpcm.play("23.wav");
  delay(3000);
   }
   else{
    digitalWrite(Speaker, LOW);
    delay(100);
   }
}

gfvalvo

A few things off the top of my head.


What type of Arduino boards?

Are you using the correct pins for I2C SDA / SCL?

Do you have the required pullup resistors for SDA ? SCL?

Have you tested that the sound even works on the second board (i.e. triggered locally, not via I2C)?

Why does your variable x (in slave code) have such a poor name?

Why isn't your variable x (in slave code) declared 'volatile' (receiveEvent is really an ISR)?

Why is your variable x (in slave code) an integer? How many different command will you be sending?
No technical questions via PM. They will be ignored. Post your questions in the forum so that all may learn.

Yepino

Hello Gfvalco

 I will try to give you a precise information of all of the questions,

 - The Arduino boards are both UNO

 - Yeah I think I am using the correct pins which are Analog A4 and Analog A5 on both of the Arduino UNO boards.

 - I don't have a pull up resistors for SCL or SDL, and if I have to how much of a resistor should I put, I didn't know that I was supposed to use a pull up resistor.

 - yes I have tested the sound on the Arduino slave alone and works perfectly.

 - I didn't get what you meant when u said a poor name for the int x?

 - If I have to change the int x or volatile into something else what should I do it, because I tried it float but it turns out that I can't transmit a floating number only a byte.

 - The only command that should go the slave Arduino board is just when the counting or the mph gets to 30mph (miles per hour).


 Thank you for your reply, can you please give some more hints?

PaulS

Quote
Thank you for your reply, can you please give some more hints?
Yes. Quit trying to use I2C. Create, on each Arduino, an instance of SoftwareSerial, and you can easily send text/binary data back and forth.

gfvalvo

Quit trying to use I2C. Create, on each Arduino, an instance of SoftwareSerial, and you can easily send text/binary data back and forth.
Agree to disagree. SoftwareSerial is notoriously flaky. I2C transactions are handled in hardware and the interface seems idea for the limited amount of info that must be transferred (play sound / don't play sound).
No technical questions via PM. They will be ignored. Post your questions in the forum so that all may learn.

Yepino

Hello guys

 Thank for your help, so you recommend me to use serial communication like Tx and Rx instead of this. Okay then I will try it using Serial and I ill let you know if I get any change.


Yepino

Hello Guys


 I tried to work it out using Serial communication but I failed. Look at my code, and I couldn't think of how to represent the character that I want to be transmitted from Arduino 1 to Arduino 2. Can you please see and tell me what changes I should make thank you for you help.


Here is the codes I tried to modify from the previous one, here I am trying to use Serial RX and TX

Master Code or Speed and lighting codes.

Code: [Select]

#include <FastLED.h>
#define hallPin  2//pin connected to read switch
#define LED_PIN 7
#define NUM_LEDS 256

CRGB leds[NUM_LEDS];


//storage variables
float radius = 10;// tire radius (in inches)- CHANGE THIS FOR YOUR OWN BIKE
int ledpin = 3;
int hallVal;
long timer = 0;// time between one full rotation (in ms)
float mph = 0.00;
float circumference;
char x = 30;
//boolean backlight;

int maxhallCounter = 100;//min time (in ms) of one rotation (for debouncing)
int hallCounter;


void setup(){

  hallCounter = maxhallCounter;
  circumference = 2*3.14*radius;
  pinMode(LED_PIN,OUTPUT);
  pinMode(ledpin,OUTPUT);
  pinMode(hallPin, INPUT);
 
  FastLED.addLeds<WS2812, LED_PIN, GRB>(leds, NUM_LEDS);
  FastLED.setBrightness(32);
//  checkBacklight();
 
//  Serial.write(12);//clear
 
  // TIMER SETUP- the timer interrupt allows preceise timed measurements of the reed switch
  //for mor info about configuration of arduino timers see http://arduino.cc/playground/Code/Timer1
  cli();//stop interrupts

  //set timer1 interrupt at 1kHz
  TCCR1A = 0;// set entire TCCR1A register to 0
  TCCR1B = 0;// same for TCCR1B
  TCNT1  = 0;
  // set timer count for 1khz increments
  OCR1A = 1999;// = (1/1000) / ((1/(16*10^6))*8) - 1
  // turn on CTC mode
  TCCR1B |= (1 << WGM12);
  // Set CS11 bit for 8 prescaler
  TCCR1B |= (1 << CS11);   
  // enable timer compare interrupt
  TIMSK1 |= (1 << OCIE1A);
 
  sei();//allow interrupts
  //END TIMER SETUP
 
  Serial.begin(9600);
//  Serial1.begin(9600);
  // Start the I2C Bus as Master
//  Wire.begin();
}



ISR(TIMER1_COMPA_vect) {//Interrupt at freq of 1kHz to measure reed switch
  hallVal = digitalRead(hallPin);//get val of hall sensor
  if (hallVal==LOW){//if reed switch is closed
    if (hallCounter == 0){//min time between pulses has passed
      mph = (53.8*float(circumference))/float(timer);//calculate miles per hour
      timer = 0;//reset timer
      hallCounter = maxhallCounter;//reset hallCounter
    }
    else{
      if (hallCounter > 0){//don't let reedCounter go negative
        hallCounter -= 1;//decrement reedCounter
      }
    }
  }
  else{//if reed switch is open
    if (hallCounter > 0){//don't let reedCounter go negative
      hallCounter -= 1;//decrement reedCounter
    }
  }
  if (timer > 2000){
    mph = 0;//if no new pulses from reed switch- tire is still, set mph to 0
  }
  else{
    timer += 1;//increment timer
  }
}



void loop(){
  if(hallVal == LOW){
    digitalWrite(ledpin, HIGH);
  }
  else{
    digitalWrite(ledpin, LOW);
  }
  //print mph once a second
  Serial.println(mph);
  if (mph == 0) {
    for(int i=0; i<=255; i++){
      leds[i] = CRGB(0,0,0);
    }
    FastLED.show();
  }
  if (mph <= 15 && mph>0) {
    for(int i=0; i<=255; i++){
      leds[i] = CRGB(255,0,0);
    }
    FastLED.show();
  }
  if (mph <= 30 && mph>15) {
    for(int i=0; i<=255; i++){
      leds[i] = CRGB(255,105,0);
    }
    FastLED.show();
  }
  if (mph > 30) {
    for(int i=0; i<=255; i++){
      leds[i] = CRGB(0,255,0);
    }
    FastLED.show();
  }
  char x = digitalRead(mph);
  Serial.write(x);

}




Code for the Sound


Code: [Select]


#include <SD.h>
#define SD_ChipSelectPin 4
#include <TMRpcm.h>
#include <SPI.h>
//#define hallPin 2
#define Speaker 9


char x [10];
TMRpcm tmrpcm;
//char mychar;

void setup() {
  // put your setup code here, to run once:


   pinMode(Speaker, OUTPUT);

  Serial.begin(9600);
 
tmrpcm.speakerPin = 9;
if(!SD.begin(SD_ChipSelectPin)){
  Serial.println("SD fail");
  return;
}
tmrpcm.setVolume(5);
}



void loop() {
  // put your main code here, to run repeatedly:
 
  Serial.readBytes(x,5);
  Serial.println(x);
if (x == 30){
  digitalWrite(Speaker, HIGH);
  tmrpcm.play("23.wav");
  delay(3000);
   }
   else{
    digitalWrite(Speaker, LOW);
    delay(100);
   }
}



Still the same observation after the speed get to 30mph there is no sound although the lighting is working perfectly. Thanks a lot for your time.

Yepino

Hello

 Is there any ideas that I can make changes to my code please. I tried the I2C and Serial communication but still not working.

 Any help will be much appreciated

Thank you.

Yepino

hey Gfvolvo


 I tried a lot of things on serial communication but I wasn't able to get any change my speed and the lighting effect are working good, but when it gets to the second Arduino it is not even responding to anything. Can you please help me here, thank you.

MorganS

You only have one sound right? So you only have one bit of data. Your information to be transmitted is just "start now" or "don't".

Use one wire and digitalWrite(). The slave can digitalRead().

Don't forget to connect the grounds.
"The problem is in the code you didn't post."

Yepino

Hello MorganS

 Yeah I only have one sound, but the thing is the SD card module is connected in the slave Arduino or receiver, so I think they are not communicating to each other as I can see it.

 What are you advising me to do? Are you saying I should use the serial Rx and TX or I2C?
And if you have seen my code can you please let me know what changes I should do on the serial communication part? What I am getting confused is when sending data to second Arduino I don't know what character or byte or number to put in.

 The idea of the project is when the speed measurement which is on the 1st Arduino gets to 30mph I wanted a data to be transmitted to the second Arduino so that the 2nd Arduino can play sound.

 Thank you for your time Morgan I really appreciate it.

Yepino

Hello Guys

 Has anyone got any idea about my issue on the serial communication between 2 arduinos  and how to transmit data from 1st Arduino to the 2nd Arduino? Please?

PaulS

Hello Guys

 Has anyone got any idea about my issue on the serial communication between 2 arduinos  and how to transmit data from 1st Arduino to the 2nd Arduino? Please?
What do you need help with? xxSerial.print() and xxSerial.read() and xxSerial.available() are all you need. You know what you print (send), so you know how much to read.

MorganS

No, I'm suggesting you use a single piece of wire (plus a ground.) No communication of bytes or anything fancy. Just on and off, HIGH and LOW.
"The problem is in the code you didn't post."

Yepino

Okay Guys

 First thanks for your help, and as you said Morgan I have tried it with one wire which is TX of the Master to the RX of the receiver and a common ground I even powered the receiver Arduino from 5v of the Master Arduino.

 What I can't figure out is that what character or number should I send using serial.read() and what to put on the serial.write().

 I got confused because when I tried to send the mph (miles per hours) it doesn't let me compile it says invalid sending of array or something like that. When I tried to define a new character and then send that character to the receiver it doesn't do anything no sound at all I am guessing it is not sending anything.

 If you look at my code there is something missing on the serial.read() and Serial.write() and the character or byte to be sent. I would appreciate if you help me there thanks a lot.

Go Up