I'm helping my cousin with a uni project that involves creating an arduino mini piano, but there's a problem with the code used.
The code she is using plays every note one by one without touching any button.
If someone could enlight me in a way to resolve the error please do.
The code: (c++)
void setup()
{
pinMode(0, INPUT);
pinMode(8, OUTPUT);
pinMode(1, INPUT);
pinMode(2, INPUT);
pinMode(3, INPUT);
pinMode(4, INPUT);
pinMode(5, INPUT);
pinMode(6, INPUT);
}
void loop()
{
if (digitalRead(0) == 1) {
tone(8, 262, 100); // play tone 48 (C4 = 262 Hz)
delay(600); // Wait for 300 millisecond(s)
}
if (digitalRead(1) == 1) {
tone(8, 294, 100); // play tone 50 (D4 = 294 Hz)
delay(600); // Wait for 300 millisecond(s)
}
if (digitalRead(2) == 1) {
tone(8, 330, 100); // play tone 52 (E4 = 330 Hz)
delay(600); // Wait for 300 millisecond(s)
}
if (digitalRead(3) == 1) {
tone(8, 349, 100); // play tone 53 (F4 = 349 Hz)
delay(600); // Wait for 300 millisecond(s)
}
if (digitalRead(4) == 1) {
tone(8, 392, 100); // play tone 55 (G4 = 392 Hz)
delay(600); // Wait for 300 millisecond(s)
}
if (digitalRead(5) == 1) {
tone(8, 440, 100); // play tone 57 (A4 = 440 Hz)
delay(600); // Wait for 300 millisecond(s)
}
if (digitalRead(6) == 1) {
tone(8, 494, 100); // play tone 59 (B4 = 494 Hz)
delay(600); // Wait for 300 millisecond(s)
}
}
I think there's nothing wrong with the code, if the intended behavior is to play one tone at time ( the one whose button is clicked ). There's probably something wrong with the way the buttons are linked to the Arduino.
Related
I am finishing up a project for school, and I am at the last step for getting my device 100% working. For a little information on the project. I am developing a wireless speedometer that tracks rpm and converts it to MPH through a hall effects sensor. The modules I am using Heltec LoRa esp32 in addition to the LoRa library through Arduino. The issue I am having is that I am trying to use the data packets received and use the sensor values sent out to be used in an if statement to activate a vibration motor to indicate if they reached a certain top speed. My code is below, and any input on how to use the packets correctly would be much appreciated. Thank you.
Receiver:
//lora stuff
#include <SPI.h>
#include <LoRa.h>
#include "SSD1306.h"
SSD1306 display(0x3c, 4, 15);
#define SS 18
#define RST 14
#define DI0 26
#define BAND 433E6
//neopixel
#include <Adafruit_NeoPixel.h>
#define LED_PIN 32
#define LED_COUNT 1
Adafruit_NeoPixel strip = Adafruit_NeoPixel(1, 32, NEO_GRB + NEO_KHZ800);
const int buttonPin = 17;// button
const int neo = 32; //
const int neoCount = 1; //number of pixels
int counter = 0; //button state counter
int buttonState = 0;
//Vibration motor
int motorPin = 25;
//level of speed in mph to trigger motor
int beginner = 10;
int intermediate = 15;
int expert = 25;
int mphVal = 0;
String data;
unsigned int totalMPH;
void setup() {
//lora
pinMode(16, OUTPUT);
digitalWrite(16, LOW); // set GPIO16 low to reset OLED
delay(50);
digitalWrite(16, HIGH);
display.init();
display.flipScreenVertically();
display.setFont(ArialMT_Plain_10);
display.setTextAlignment(TEXT_ALIGN_LEFT);
// button
pinMode(buttonPin, INPUT);
//motor
pinMode(motorPin, OUTPUT);
//neopixel
strip.begin();
strip.show();
strip.setBrightness(50);
Serial.begin(115200);
//lora initial
while (!Serial); //if just the the basic function, must connect to a computer
delay(100);
Serial.println("Speed Receiver");
display.drawString(5, 5, "Speed Receiver");
display.display();
SPI.begin(5, 19, 27, 18);
LoRa.setPins(SS, RST, DI0);
if (!LoRa.begin(BAND)) {
display.drawString(5, 25, "Starting LoRa failed!");
while (1);
}
Serial.println("LoRa Initial OK!");
display.drawString(5, 25, "LoRa Initializing OK!");
display.display();
}
void loop() {
// try to parse packet
int packetSize = LoRa.parsePacket();
if (packetSize) {
// received a packets
//Serial.print("Received packet. ");
display.clear();
display.setFont(ArialMT_Plain_16);
display.drawString(3, 0, "Received Speed ");
display.display();
// read packet
while (LoRa.available()) {
String data = LoRa.readString();
Serial.print(data);
display.drawString(20, 22, data);
display.display();
// if speed reaches x then motor will buzz
if (data.equals("MPH: 12.5")) {
digitalWrite(motorPin, HIGH);
delay(10);
digitalWrite(motorPin, LOW);
delay(10);
}
}
// print RSSI of packet
//Serial.print(" with RSSI ");
//Serial.println(LoRa.packetRssi());
// display.drawString(20, 45, "RSSI: ");
// display.drawString(70, 45, (String)LoRa.packetRssi());
// display.display();
}
//taking the packet and turning it into an int from string
//String data = data.toInt();
//int data = totalMPH;
//float totalMPH = data.toFloat();
// char data;
// float totalMPH;
//totalMPH = atof(data);
//Serial.println(totalMPH);
//button
buttonState = digitalRead(buttonPin);
if (buttonState == HIGH) {
counter++;
delay(150);
}
//button states with three colors
//beginner
else if (counter == 0) {
//Serial.println("pushed");
strip.setPixelColor(0, 255, 0, 0);
strip.show();
//Serial.println(0);
display.drawString(10, 45, "REC: 10 MPH");
display.display();
//vibration motor will trigger if the speed recieved is less then or equal to 12mph
// digitalWrite(motorPin, HIGH);
// delay(4000);
// digitalWrite(motorPin, LOW);
// delay(120000);
}
//intermediate
else if (counter == 1) {
strip.setPixelColor(0, 0, 255, 0);
strip.show();
Serial.println(1);
display.drawString(10, 45, "REC: 15 MPH");
display.display();
//vibration motor will trigger if the speed recieved is less then or equal to 17mph
// digitalWrite(motorPin, HIGH);
// delay(4000);
// digitalWrite(motorPin, LOW);
// delay(240000);
//digitalWrite(motorPin, LOW);
}
//expert
else if (counter == 2) {
strip.setPixelColor(0, 0, 0, 255);
strip.show();
Serial.print(2);
display.drawString(10, 45, "REC: 20 MPH");
display.display();
//digitalWrite(motorPin, LOW);
}
//reset settings
else {
counter = 0;
}
}
Transmitter:
//lora
#include <SPI.h>
#include <LoRa.h>
#include "SSD1306.h"
#include <Arduino.h>
#include <Bounce2.h>
Bounce hall = Bounce();
SSD1306 display(0x3c, 4, 15);
#define SS 18
#define RST 14
#define DI0 26
#define BAND 433E6 //915E6
int counter = 0;
int rpmTimer = 0;
int rpmInterval = 1000;
void setup() {
//board and lcd
pinMode(25, OUTPUT); //Send success, LED will bright 1 second
pinMode(16, OUTPUT);
digitalWrite(16, LOW); // set GPIO16 low to reset OLED
delay(50);
digitalWrite(16, HIGH);
// sensor and led
hall.attach(37, INPUT);
hall.interval(1);
//pinMode(led, OUTPUT);
//pinMode(hallSens, INPUT);
Serial.begin(115200);
//lcd
while (!Serial); //If just the the basic function, must connect to a computer
// Initialising the UI will init the display too.
display.init();
display.flipScreenVertically();
display.setFont(ArialMT_Plain_10);
display.setTextAlignment(TEXT_ALIGN_LEFT);
display.drawString(5, 5, "LoRa Sender");
display.display();
//lora
SPI.begin(5, 19, 27, 18);
LoRa.setPins(SS, RST, DI0);
Serial.println("LoRa Sender");
if (!LoRa.begin(BAND)) {
Serial.println("Starting LoRa failed!");
while (1);
}
Serial.println("LoRa Initial OK!");
display.drawString(5, 20, "LoRa Initializing OK!");
display.display();
delay(10);
}
void loop() {
hall.update();
if(hall.rose()){
counter++;
}
if(millis() - rpmTimer > rpmInterval){
float rpm = counter * 60;
float rph = rpm * 60;
float dia = 0.00004349;
float cir = dia * 3.14;
float totalMPH = rph * cir;
Serial.println(totalMPH);
rpmTimer = millis();
counter = 0;
//sending packet
LoRa.beginPacket();
LoRa.print("MPH: " + String(totalMPH));
LoRa.endPacket();
//LoRa.sleep(); //puts lora receiver to sleep probably dont need
digitalWrite(25, HIGH); // turn the LED on (HIGH is the voltage level)
delay(10); // wait for a second
digitalWrite(25, LOW); // turn the LED off by making the voltage LOW
delay(100); // wait for a second
//delay(300);
}
}
In terms of wire-based API design:
// packet is the packet from the transmitter
String packet = "S12.5"
String measurement = packet.substring(0, 1); // "S"
if (measurement == "S") {
// at this point we know that the rest of the message is the MPH
String data = packet.substring(1, strlen(packet)-1); // "12.5"
float mph = data.toFloat();
if (mph >= TOP_SPEED) {
doSomething();
}
else {
doSomethingElse();
}
}
you could use charAt(0) to get the measurement instead of substring() if you know there are less than 25 sensors on the network.
each measurement would have its own char at the start of message and the data that related to that measurement would immediately follow. The sender and receiver are therefore interacting like a client/server in an API exchange. There is an implicit contract between them such that, when the transmitter says "S12.5", the receiver knows that means 12.5MPH. It's your system so you can design the communication packets any way you like.
I wanted a lighted RECORDING sign to change colors based on the play state of my recording software. I wrote the Arduino code below to turn on one of three relays (LED Lights) when I press either STOP, PLAY, or RECORD in the music software Cubase. When pressed, Cubase transmits these midi strings:
Cubase sends "B0 0C 0E B0 2C 44" when it begins to PLAY
Cubase sends "B0 0C 0E B0 2C 43" when it begins to STOP
Cubase sends "B0 0C 0E B0 2C 45" when it begins to RECORD
I had code that found the first BYTE, then waited for the second BYTE. But that was unnecessary.
All I need is, for example, is "B0 2C 44" (or 176-44-68 decimal) to appear, and I turn on the PLAY (Green) LED.
It works.
However, not all the time. Every fourth or fifth time, it doesn't sense it. I put the hardware I'm using in the notes.
I've done days of research and am aware of others who are experiencing the same issue, but I can't seem to find a solution. Thanks for any advice you may have.
/*RECORDING SIGN for Steinberg Cubase Pro 11
Copyright (c) 2021 by Tom Sylvester, Inc. A North Carolina Corp
Feel free to use this code in your own project. Just credit me.
Monitoring MidiOX, I determined:
Cubase sends "B0 0C 0E B0 2C 44" when it begins to PLAY
Cubase sends "B0 0C 0E B0 2C 43" when it begins to STOP
Cubase sends "B0 0C 0E B0 2C 45" when it begins to RECORD
Cubase sends "B0 0C 0E B0 2C 42" when it begins to SCRUB FWD
Cubase sends "B0 0C 0E B0 2C 41" when it begins to SCRUB REW
Cubase sends "B0 0C 0F B0 2C 43" when LOOP is set to ON
Cubase sends "B0 0C 0F B0 2C 03" when LOOP is set to OFF
The following code takes these strings and turns the LED Relays On/Off.
PARTS:
Arduino Uno R3 Microcontroller ($14)
UBld.it MIDI Breakout Board ($12)
HiLetgo 5V 4 Channel Relay Shield ($8)
5V LED Strip Light ($9)
Striveday 22 AWG 5 conductor wire ($18)
FORE MIDI to USB Interface MIDI Cable Adapter ($20)
Wolfwhoop PW-D Control Buck Converter 6-24V to 5V
1.5A Step-Down Regulator Module Power Inverter Volt Stabilizer ($2)
9V DC Adapter ($9)
Radio Shack Project Enclosure (5x2x2.5) ($10)
SUBTOTAL: $93
Custom Etched Acrylic Logo (8.5x11x.25) approx $22
TOTAL: $115
*/
// VARIABLES
int dataStop = 67;
int dataPlay = 68;
int dataRecord = 69;
int dataFwd = 66;
int dataRev = 65;
int StayOnRecord = 0;
// MIDI
byte status1;
byte data11;
byte data12;
// RELAYS
#define relay2Blue 6
#define relay3Green 5
#define relay4Red 4
void setup() {
Serial.begin(31250);
pinMode(relay2Blue, OUTPUT);
pinMode(relay3Green, OUTPUT);
pinMode(relay4Red, OUTPUT);
digitalWrite(relay2Blue, HIGH); // TURN ON BLUE RELAY (#2) INITIALLY
}
void checkMIDI() {
do {
if (Serial.available()) {
status1 = Serial.read(); // read first byte
data11 = Serial.read(); // read next byte
data12 = Serial.read(); // read final byte
// STOP
if ((status1 == 176) && (data11 == 44) && (data12 == dataStop)) {
StayOnRecord = 0;
digitalWrite(relay2Blue, HIGH);
digitalWrite(relay3Green, LOW);
digitalWrite(relay4Red, LOW);
}
// RECORD
if ((status1 == 176) && (data11 == 44) && (data12 == dataRecord)) {
StayOnRecord = 1;
digitalWrite(relay2Blue, LOW);
digitalWrite(relay3Green, LOW);
digitalWrite(relay4Red, HIGH);
}
// PLAY
if ((status1 == 176) && (data11 == 44) && (data12 == dataPlay)) {
if (StayOnRecord == 0) { // Cubase sends a PLAY command after RECORD, so this keeps PLAY (GREEN) from lighting up during RECORD (RED)
digitalWrite(relay2Blue, LOW);
digitalWrite(relay3Green, HIGH);
digitalWrite(relay4Red, LOW);
}
StayOnRecord = 0; // ...then RESETs it.
}
// FAST FORWARD
if ((status1 == 176) && (data11 == 44) && (data12 == 66)) {
for (int i=1; i<=6 ; i++) {
digitalWrite(relay2Blue, HIGH);
digitalWrite(relay4Red, LOW);
digitalWrite(relay3Green, HIGH); // TURN ON ALL RELAYS
delay(20);
digitalWrite(relay2Blue, LOW);
digitalWrite(relay4Red, LOW);
digitalWrite(relay3Green, LOW); // TURN OFF ALL RELAYS
delay(20);
}
digitalWrite(relay3Green, LOW);
digitalWrite(relay4Red, LOW);
digitalWrite(relay2Blue, HIGH); // TURN ON BLUE RELAY (#2)
StayOnRecord = 0;
delay(10);
}
// FAST REVERSE
if ((status1 == 176) && (data11 == 44) && (data12 == 65)) {
for (int i=1; i<=6 ; i++) {
digitalWrite(relay2Blue, HIGH);
digitalWrite(relay4Red, LOW);
digitalWrite(relay3Green, HIGH); // TURN ON ALL RELAYS
delay(20);
digitalWrite(relay2Blue, LOW);
digitalWrite(relay4Red, LOW);
digitalWrite(relay3Green, LOW); //TURN OFF ALL RELAYS
delay(20);
}
digitalWrite(relay3Green, LOW);
digitalWrite(relay4Red, LOW);
digitalWrite(relay2Blue, HIGH); //TURN ON BLUE RELAY (#2)
StayOnRecord = 0;
delay(10);
}
}
}
while (Serial.available() > 2); // when at least three bytes available
}
void loop(){
checkMIDI();
delay(10);
}
Arduino, with Relay Shield:
Working Recording Sign:
Cool project!
Each time through loop() you call your checkMIDI(), which tests if a character is available, but then tries to read three values. Changing the do while to a while (Serial.available() >= 3) { ... } might fix it, and that might be enough.
One option - use a MIDI library, and let it do the collecting and parsing for you. You would define a callback to get the CC commands, and decide what to do with them. https://github.com/FortySevenEffects/arduino_midi_library
Another option, re-do your scanning to set some flags, and use the loop(). Here's a rough skeleton:
const byte IDLE = 0, NEEDCC = 1, NEEDNUM = 2;
byte midiscanstate = IDLE;
// this is inside loop()
if serial available
b = serial read
switch midiscanstate
case IDLE
if b == B0
midiscanstate = NEEDCC
case NEEDCC
if b == 0x2C
midiscanstate = NEEDNUM
else
midiscanstate = IDLE
case NEEDNUM
doaction(b)
midiscanstate = IDLE
default
midiscanstate = IDLE
Draw out the states and the bytes which change state to make sure I've got it right. I think that will work. (should probably ignore midi real-time messages if they get in the way). HTH! Have fun!
#aMike, thanks for your thoughts. Your Callback recommendation is ALMOST working. It's going to the doCC callback below (I tested it with != 0 and also by simply turning on relays within the procedure). But in order to do an IF..THEN or CASE, I need to know what status1, data11, and data12 are coming back as. Alas, with no Serial Monitor available (<>9600 baud), I'm in a room with the lights out. It should be sending "B0 2C 44" but apparently it's not. You've been very helpful--ALMOST THERE!
#include <MIDI.h>
MIDI_CREATE_DEFAULT_INSTANCE();
void handleControlChange(byte status1, byte data11, byte data12);
// VARIABLES
byte dataStop = 0x43;
byte dataPlay = 0x44;
byte dataRecord = 0x45;
int StayOnRecord = 0;
// RELAYS
#define relay2Blue 6
#define relay3Green 5
#define relay4Red 4
void doCC(byte status1, byte data11, byte data12)
{
// STOP
if ((status1 == 0xB0) && (data11 == 0x2C) && (data12 == 0x43)) {
StayOnRecord = 0;
digitalWrite(relay2Blue, HIGH);
digitalWrite(relay3Green, LOW);
digitalWrite(relay4Red, LOW);
}
// RECORD
if ((status1 == 0xB0) && (data11 == 0x2C) && (data12 == 0x45)) {
StayOnRecord = 1;
digitalWrite(relay2Blue, LOW);
digitalWrite(relay3Green, LOW);
digitalWrite(relay4Red, HIGH);
}
// PLAY
if ((status1 == 0xB0) && (data11 == 0x2C) && (data12 == 0x44)) {
if (StayOnRecord == 0) { // Cubase sends a PLAY command after RECORD, so this keeps PLAY (GREEN) from lighting up during RECORD (RED)
digitalWrite(relay2Blue, LOW);
digitalWrite(relay3Green, HIGH);
digitalWrite(relay4Red, LOW);
}
StayOnRecord = 0; // ...then RESETs it.
}
}
void setup() {
pinMode(relay2Blue, OUTPUT);
pinMode(relay3Green, OUTPUT);
pinMode(relay4Red, OUTPUT);
digitalWrite(relay2Blue, HIGH); // TURN ON the BLUE LED Relay (#2) INITIALLY
MIDI.begin(MIDI_CHANNEL_OMNI); // Listen on all channels
// MIDI.turnThruOff();
MIDI.setHandleControlChange(doCC);
}
void loop()
{
MIDI.read();
}
Thanks SO much, #aMike. Your ideas were SPOT ON. This code works perfectly, now, with zero drop-outs:
#include <MIDI.h>
MIDI_CREATE_DEFAULT_INSTANCE();
void handleControlChange(byte status1, byte data11, byte data12);
// VARIABLES
byte dataStop = 0x43;
byte dataPlay = 0x44;
byte dataRecord = 0x45;
byte dataFFWD = 0x42;
byte dataFREV = 0x41;
int StayOnRecord = 0;
// RELAYS
#define relay2Blue 6
#define relay3Green 5
#define relay4Red 4
void doCC(byte status1, byte data11, byte data12){
// get note value
status1 = MIDI.getChannel();
data11 = MIDI.getData1();
data12 = MIDI.getData2();
// STOP
if (data12 == dataStop) {
StayOnRecord = 0;
digitalWrite(relay2Blue, HIGH);
digitalWrite(relay3Green, LOW);
digitalWrite(relay4Red, LOW);
}
// RECORD
if (data12 == dataRecord) {
StayOnRecord = 1;
digitalWrite(relay2Blue, LOW);
digitalWrite(relay3Green, LOW);
digitalWrite(relay4Red, HIGH);
}
// PLAY
if (data12 == dataPlay) {
if (StayOnRecord == 0) { // Cubase sends a PLAY command after RECORD, so this keeps PLAY (GREEN) from lighting up during RECORD (RED)
digitalWrite(relay2Blue, LOW);
digitalWrite(relay3Green, HIGH);
digitalWrite(relay4Red, LOW);
}
StayOnRecord = 0; // ...then RESETs it.
}
// Fast FWD
if (data12 == dataFFWD) {
StayOnRecord = 0;
digitalWrite(relay2Blue, HIGH);
digitalWrite(relay3Green, HIGH);
digitalWrite(relay4Red, LOW);
}
// Fast REV
if (data12 == dataFREV) {
StayOnRecord = 0;
digitalWrite(relay2Blue, LOW);
digitalWrite(relay3Green, HIGH);
digitalWrite(relay4Red, HIGH);
}
}
void setup() {
pinMode(relay2Blue, OUTPUT);
pinMode(relay3Green, OUTPUT);
pinMode(relay4Red, OUTPUT);
digitalWrite(relay2Blue, HIGH); // TURN ON the BLUE LED Relay (#2) INITIALLY
MIDI.begin(MIDI_CHANNEL_OMNI); // Listen on all channels
MIDI.turnThruOff();
MIDI.setHandleControlChange(doCC);
}
void loop()
{
MIDI.read();
}
I'm trying to implement a car warning sound using a piezo buzzer and an ultrasonic sensor.If an object is 50 to 30 cm away, it will sound for 1 second and try to turn off the sound for 1 second, but I can't think of a way to implement this code. Can you help me? Here is my code.
#define echoPin 4
#define trigPin 3
#define buzPin 5
void setup() {
Serial.begin(9600);
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
pinMode(buzPin, OUTPUT);
}
void loop() {
digitalWrite(trigPin, LOW);
digitalWrite(echoPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
unsigned long duration = pulseIn(echoPin, HIGH);
float distance = ((float)(340 * duration) / 10000) / 2;
Serial.print(distance);
Serial.println("cm");
if (distance <= 50 && distance > 31)
{
tone(buzPin, 391, 1000);
}
else if (distance <= 30 && distance > 21)
{
tone(buzPin, 391, 500);
}
else if (distance <= 20 && distance > 11)
{
tone(buzPin, 391, 100);
}
else if (distance <= 10)
{
tone(buzPin, 391);
}
else {
noTone(buzPin);
}
}
After each time you tell the arduino to start making a tone (this is the tone() command) add some delay. To do this just follow the instructions bellow:
//code
if(statement)
{
tone(buzPin, 391, 500);
delay(x); //x=with the delay you want the buzzer to sound in ms
noTone(buzPin); //after that the sound stops
delay(y); //y=with the delay you want the buzzer to be silent in ms
}
I have made a circuit involving 3 strings of LEDs.
They are supposed to glow at a low intensity initially.
Now when pin 2 on Arduino goes HIGH momentarily, the LED strings glow brighter one by one and then stop. AND, if the pin 2 is kept HIGH, then the transition should continue as long as pin 2 is HIGH.
The problem is that if I make pin 2 HIGH permanently via a push button, the transition occurs 4 times and then it stops. No transition occurs after that even if i again make the pin 2 HIGH after some time.
The code is given below:
const int pin1 = 9;
const int pin2 = 10;
const int pin3 = 11;
const int button = 2;
int val = 0;
//int brightness = 0;
void setup(){
Serial.begin(9600);
pinMode(pin1, OUTPUT);
pinMode(pin2, OUTPUT);
pinMode(pin3, OUTPUT);
pinMode(button, INPUT);
}
void loop(){
while(true)
{
val = digitalRead(button);
if(val == HIGH)
{
if(Serial.available())
{
long int brightness = Serial.read();
analogWrite(pin1, 255);
delay(1000);
analogWrite(pin2, 255);
delay(1000);
analogWrite(pin3, 255);
delay(1000);
analogWrite(pin1, brightness);
analogWrite(pin2, brightness);
analogWrite(pin3, brightness);
delay(1000);
}
}
}
}
If you really want to configure your dimmed brightness after each reset of your arduino, you should rearrange your source in a way that reading from the serial port doesn't block your transition, while still making sure your "brightness" has a predefined value:
// global variable with preset value
long int brightness = 64;
// loop function
// http://arduino.cc/en/pmwiki.php?n=Reference/Loop
void loop(){
// check for new brightness value
if(Serial.available())
{
int brightness = Serial.read();
}
// check for pressed button
val = digitalRead(button);
if(val == HIGH)
{
// start light cycle
analogWrite(pin1, 255);
delay(1000);
analogWrite(pin2, 255);
delay(1000);
analogWrite(pin3, 255);
delay(1000);
analogWrite(pin1, brightness);
analogWrite(pin2, brightness);
analogWrite(pin3, brightness);
delay(1000);
}
}
I need to transmit an infrared signal using the Arduino to run a Samsung TV.
I tried the following code:
// Lucas Eckels
// Http://lucaseckels.com
// IR remote control emitter for NEC protocol remote, as described at
// Http://www.sbprojects.com/knowledge/ir/nec.htm
// Tested on a Samsung LCD TV.
#include <util/delay.h>
#define IR_PIN 13
// With CONTINOUS defined, the first command is repeated continuously until
// You reset the Arduino. Otherwise, it sends the code once, then waits for
// Another command.
#define CONTINUOUS
// Times are in microseconds
#define ON_START_TIME 4500
#define OFF_START_TIME 4500
#define ON_TIME 580
#define OFF_TIME_ONE 1670
#define OFF_TIME_ZERO 540
#define DEVICE_1 7
#define DEVICE_2 7
void setup() {
pinMode (IR_PIN, OUTPUT);
digitalWrite(IR_PIN, LOW);
Serial.begin(9600);
delay(1000);
Serial.write("Starting up..\n");
}
byte command = 0;
int commandCount = 0;
bool commandReady = false;
void loop() {
if (commandReady) {
Serial.print("Writing command");
Serial.print(command, DEC);
Serial.print("\n");
writeStart();
// Writing device code
writeByte(DEVICE_1);
writeByte(DEVICE_2);
// Writing command code
writeByte(command);
writeByte(~command);
writeEnd();
delay(100);
#ifndef CONTINUOUS
commandReady = false;
command = 0;
commandCount = 0;
#endif
return;
}
if (Serial.available () > 0) {
// Read in a 3-digit decimal command code.
byte incoming = Serial.read();
if (incoming <= '9 ' || incoming >= '0') {
command *= 10;
command += incoming - '0 ';
++commandCount;
}
if (commandCount == 3) {
commandReady = true;
}
}
}
void writeStart() {
modulate(ON_START_TIME);
delayMicroseconds(OFF_START_TIME);
}
void writeEnd() {
modulate(ON_TIME);
}
void writeByte(byte val) {
// Starting with the LSB, write out the
for (int i = 0x01; i & 0xFF; i <<= 1) {
modulate(ON_TIME);
if (val & i) {
delayMicroseconds (OFF_TIME_ONE);
} else {
delayMicroseconds (OFF_TIME_ZERO);
}
}
}
void modulate(int time) {
int count = time / 26;
byte portb = PORTB;
byte portbHigh = portb | 0x20; // Pin 13 is controlled by 0x20 on PORTB.
byte portbLow = portb & ~0x20;
for (int i = 0; i <= count; i++) {
// The ideal version of this loop would be:
// DigitalWrite(IR_PIN, HIGH);
// DelayMicroseconds(13);
// DigitalWrite(IR_PIN, LOW);
// DelayMicroseconds(13);
// But I had a hard time getting the timing to work right. This approach was found
// Through experimentation.
PORTB = portbHigh;
_delay_loop_1(64);
PORTB = portbLow;
_delay_loop_1(64);
}
PORTB = portb;
}
The code compiles but is not working for me.
I wrote this to control an LG TV and Sony Amplifier. You would just need to save your own raw codes to the header file and off you go:
https://github.com/gotnull/SiriProxy-TV-Control/blob/master/arduino-remote/Remote/Remote.pde
// This procedure sends a 38KHz pulse to the IRledPin
// for a certain # of microseconds. We'll use this whenever we need to send codes
void pulseIR(long microsecs) {
// we'll count down from the number of microseconds we are told to wait
cli(); // this turns off any background interrupts
while (microsecs > 0) {
// 38 kHz is about 13 microseconds high and 13 microseconds low
digitalWrite(IRledPin, HIGH); // this takes about 3 microseconds to happen
delayMicroseconds(10); // hang out for 10 microseconds
digitalWrite(IRledPin, LOW); // this also takes about 3 microseconds
delayMicroseconds(10); // hang out for 10 microseconds
// so 26 microseconds altogether
microsecs -= 26;
}
sei(); // this turns them back on
}
I'd also recommend taking a read through Ladyada's wonderful tutorial:
Sensor tutorials - IR remote receiver/decoder tutorial
DelayMicroseconds is fairly accurate, and will be precise enough for your task. However you are right in staying away from DigitalWrite. It takes about 50 times as many clock-cycles to complete compared to direct port assignment (PORTB=... ) which takes exactly one. You will only be able to time a 38MHz pulse that way. I don't know what your _delay_loop_1 does, but everything else seems okay. (aside from the "i + +" but that's a cut'n'paste typo I guess)
Have you checked that it actually lights up? a phone or cheap digicam will actually show you the IR on the screen.