Permalänk

Vart felar det? (Arduino)

Hej hej hallå.

Några av er vet kanske att jag håller på med ett större projekt i form av en radiostyrd R2D2.

Nu har jag satt mig för att försöka förstå och koppla ihop min arduino som ska användas för automatisering av ljudet, tillsammans med en avståndssensor och en MP3 Trigger.

Att enbart koppla ihop Arduinon och MP3 triggern och få den att låta är inga problem.
Men när jag kopplar in avståndssensorn så vill den inte alls.

Jag är HELT grön när det gäller att leka med sånt här, så ja hoppas ni har lite överseende

Koden som funkar, spelar upp random ljud med 5 sek mellanrum (utan avståndssensorn):

//Test med Arduino och MP3 Trigger för att automatisera ljudet// /////////////////////////////////////////////////// #include <MP3Trigger.h> MP3Trigger trigger; /////////////////////////////////////////////////// void setup() { //start serial communication with the trigger (over Serial) trigger.setup(); } /////////////////////////////////////////////////// void loop() { trigger.play(1); // Trigga olika ljud delay(5000); }

Och här är koden som jag använder för avståndssensorn:

//Test med Arduino och MP3 Trigger för att automatisera ljudet// /////////////////////////////////////////////////// #define trigPin 2 #define echoPin 3 #include <MP3Trigger.h> MP3Trigger trigger; /////////////////////////////////////////////////// void setup() { //start serial communication with the trigger (over Serial) trigger.setup(); Serial.begin (9600); pinMode(trigPin, OUTPUT); pinMode(echoPin, INPUT); } /////////////////////////////////////////////////// void loop() { int duration, distance; digitalWrite(trigPin, HIGH); // Added this line delayMicroseconds(200); // Added this line digitalWrite(trigPin, LOW); duration = pulseIn (echoPin, HIGH); distance = (duration/2) /29.1; Serial.print (distance); Serial.print ("cm "); delay(100); { if (distance < 30) // Numret avger vid vilket avstånd det ska triggas { trigger.play(1); delay(5000); } else { trigger.play(random(32,54)); delay(5000); }}}

Jag ser avståndet i monitoren på datorn, men när avståndet blir under 30cm så händer ingenting, dessutom händer det ingenting om avståndet är högre heller för den delen. Men tanken där är ju att den ska spela ett random.

Visa signatur

Details is everything, the rest is just details.

[Bygglogg] Fullskalig radiostyrd R2D2: https://www.sweclockers.com/galleri/11953-radiostyrd-r2d2-byg...

Permalänk
Medlem

Har inte superkoll, men ska det verkligen påbörjas ett nytt block efter "delay(100);" och vad har det för funktion? Tänkte annars att if-satsen skulle ligga efter delay utan klammerparantesen.

Permalänk
Medlem
Skrivet av DeepSilence:

Hej hej hallå.

Några av er vet kanske att jag håller på med ett större projekt i form av en radiostyrd R2D2.

Nu har jag satt mig för att försöka förstå och koppla ihop min arduino som ska användas för automatisering av ljudet, tillsammans med en avståndssensor och en MP3 Trigger.

Att enbart koppla ihop Arduinon och MP3 triggern och få den att låta är inga problem.
Men när jag kopplar in avståndssensorn så vill den inte alls.

Jag är HELT grön när det gäller att leka med sånt här, så ja hoppas ni har lite överseende

Koden som funkar, spelar upp random ljud med 5 sek mellanrum (utan avståndssensorn):

//Test med Arduino och MP3 Trigger för att automatisera ljudet// /////////////////////////////////////////////////// #include <MP3Trigger.h> MP3Trigger trigger; /////////////////////////////////////////////////// void setup() { //start serial communication with the trigger (over Serial) trigger.setup(); } /////////////////////////////////////////////////// void loop() { trigger.play(1); // Trigga olika ljud delay(5000); }

Och här är koden som jag använder för avståndssensorn:

//Test med Arduino och MP3 Trigger för att automatisera ljudet// /////////////////////////////////////////////////// #define trigPin 2 #define echoPin 3 #include <MP3Trigger.h> MP3Trigger trigger; /////////////////////////////////////////////////// void setup() { //start serial communication with the trigger (over Serial) trigger.setup(); Serial.begin (9600); pinMode(trigPin, OUTPUT); pinMode(echoPin, INPUT); } /////////////////////////////////////////////////// void loop() { int duration, distance; digitalWrite(trigPin, HIGH); // Added this line delayMicroseconds(200); // Added this line digitalWrite(trigPin, LOW); duration = pulseIn (echoPin, HIGH); distance = (duration/2) /29.1; Serial.print (distance); Serial.print ("cm "); delay(100); { if (distance < 30) // Numret avger vid vilket avstånd det ska triggas { trigger.play(1); delay(5000); } else { trigger.play(random(32,54)); delay(5000); }}}

Jag ser avståndet i monitoren på datorn, men när avståndet blir under 30cm så händer ingenting, dessutom händer det ingenting om avståndet är högre heller för den delen. Men tanken där är ju att den ska spela ett random.

Lägg en serial.print i if-satsen och kolla ifall den verkligen kommer dit!

Sitter själv och mejar med en arduino till ett ex projekt och det är ett helvete när man inte kan debugga kod!

Edit: måste hålla med ovanstående, det är en måsvinge efter delat(100); ovanför if-satsen. Det känns som om den hamnat fel!

Visa signatur

~. Citera så jag hittar tillbaka .~

Permalänk
Skrivet av KeVVa:

Lägg en serial.print i if-satsen och kolla ifall den verkligen kommer dit!

Sitter själv och mejar med en arduino till ett ex projekt och det är ett helvete när man inte kan debugga kod!

Edit: måste hålla med ovanstående, det är en måsvinge efter delat(100); ovanför if-satsen. Det känns som om den hamnat fel!

Tack för snabba svar!

Testade som du skrev att lägga till en Serial.print, och den kommer både till if och else. Så det sjuka är att den inte vill skicka signalen till MP3 triggern.

Tog även bort måsvingen, men utan någon större framgång i det stora hela

Visa signatur

Details is everything, the rest is just details.

[Bygglogg] Fullskalig radiostyrd R2D2: https://www.sweclockers.com/galleri/11953-radiostyrd-r2d2-byg...

Permalänk
Medlem

Tror duration och distance borde vara av en annan typ än Integers också. (Sorry för klent svar, men är på mobilen)

Permalänk
Medlem
Skrivet av DeepSilence:

Tack för snabba svar!

Testade som du skrev att lägga till en Serial.print, och den kommer både till if och else. Så det sjuka är att den inte vill skicka signalen till MP3 triggern.

Tog även bort måsvingen, men utan någon större framgång i det stora hela

Prova lägg en delay i början av loop() på 100ms!

Visa signatur

~. Citera så jag hittar tillbaka .~

Permalänk
Skrivet av KeVVa:

Prova lägg en delay i början av loop() på 100ms!

Testade detta, nada..

Men det slog mig just att jag kanske skulle skriva med detta också. När jag kollar monitorn när jag har trigger.play"blablabla" i koden så får jag ett "p" med ett slumpmässigt tecken efter mellan varje loop. Här följer ett litet urklipp från monitorn; "p5176cm p'176cm p'177cm p(65cm p(176cm p-179cm".

Säger det någon någonting?

Visa signatur

Details is everything, the rest is just details.

[Bygglogg] Fullskalig radiostyrd R2D2: https://www.sweclockers.com/galleri/11953-radiostyrd-r2d2-byg...

Permalänk

Fick det att fungera genom att skriva trigger.setup(); EFTER att jag pinMode för in och ut på avståndssensorn. Så nu kör den ett random ljud om inget blockerar sensorn, och spelar ett specifikt ljud när jag blockar

Det jag nu har problem med är att få sensorn att vara ständigt "aktiv". Ja vill ju att den ska triggas så fort jag blockar den, och inte efter att loopen har gått runt ett varv, vilket den gör nu.

Några tips?

Visa signatur

Details is everything, the rest is just details.

[Bygglogg] Fullskalig radiostyrd R2D2: https://www.sweclockers.com/galleri/11953-radiostyrd-r2d2-byg...

Permalänk
Medlem

Om du inte hade fördröjningen på 5s mellan iterationerna skulle du få bättre responsivitet, men utan att ha någon vetskap om ljud-enheten kanske fördröjningen är nödvändig av andra skäl?

Om så, skulle du istället kunna låta den "stå kvar" i det senast uppspelade ljudet så länge som tiden underskrider 5s genom att använda exempelvis millis(), men att byta läge om distansen ändras.

Permalänk
Medlem
Skrivet av DeepSilence:

Fick det att fungera genom att skriva trigger.setup(); EFTER att jag pinMode för in och ut på avståndssensorn. Så nu kör den ett random ljud om inget blockerar sensorn, och spelar ett specifikt ljud när jag blockar

Det jag nu har problem med är att få sensorn att vara ständigt "aktiv". Ja vill ju att den ska triggas så fort jag blockar den, och inte efter att loopen har gått runt ett varv, vilket den gör nu.

Några tips?

Det är som är krångligt med arduino, man har bara en tråd.

unsigned long currentMillis = millis(); long intervall = 5000 if(currentMillis - previousMillis > interval) { previousMillis = currentMillis; //spela musik här }

Problemet är att när currentmillis och previousmillis blir för stora så kommer programmet inte fungera, om inte annat kräver det mycket minne!

En annan variant vore att räkna på en variabel. Den ger dock inte exakt tid!

Int i = 0; Void loop() { //do something If(i > 5000) { //play music i = 0; } //räkna upp i varje varv i++; }

Du får experimentera dig fram!
Sorry för den fula koden men sitter på surfplattan!

Visa signatur

~. Citera så jag hittar tillbaka .~

Permalänk
Medlem
Skrivet av KeVVa:

Det är som är krångligt med arduino, man har bara en tråd.

unsigned long currentMillis = millis(); long intervall = 5000 if(currentMillis - previousMillis > interval) { previousMillis = currentMillis; //spela musik här }

Problemet är att när currentmillis och previousmillis blir för stora så kommer programmet inte fungera, om inte annat kräver det mycket minne!

En annan variant vore att räkna på en variabel. Den ger dock inte exakt tid!

Int i = 0; Void loop() { //do something If(i > 5000) { //play music i = 0; } //räkna upp i varje varv i++; }

Du får experimentera dig fram!
Sorry för den fula koden men sitter på surfplattan!

För att förtydliga, detta inträffar när du får overflow på variabeln, vilket resulterar i att du i

if(currentMillis - previousMillis > interval)

subtraherar ett väldigt stort tal från ett väldigt litet, vilket innebär att det tar väldigt lång tid innan villkoret > interval uppfylls. Lösningen till detta problem är mycket enkel, det är bara att casta resultatet till en unsigned long, vilket innebär att det negativa resultatet istället kommer att betraktas som ett väldigt stort tal.

if ((unsigned long)(currentMillis-previousMillis) > interval)

Permalänk
Medlem
Skrivet av reinholdsson:

För att förtydliga, detta inträffar när du får overflow på variabeln, vilket resulterar i att du i

if(currentMillis - previousMillis > interval)

subtraherar ett väldigt stort tal från ett väldigt litet, vilket innebär att det tar väldigt lång tid innan villkoret > interval uppfylls. Lösningen till detta problem är mycket enkel, det är bara att casta resultatet till en unsigned long, vilket innebär att det negativa resultatet istället kommer att betraktas som ett väldigt stort tal.

if ((unsigned long)(currentMillis-previousMillis) > interval)

De må vara så men variabeln ifrån millis() overflowar själv efter 50 dagar och börjar om ifrån noll enligt dokumentationen. Det är väl bara en petites, och inget som påverkar programmet. Dock så drar det mycket minne!

Koden kommer ifrån arduinos tutorial och där castar de inte, jag castar inte heller i min kod.
http://arduino.cc/en/Tutorial/BlinkWithoutDelay

Edit: En arduino long variabel använder ca. 4 byte. Det var mindre än vad jag trodde. Arduino uno (ATmega328) har 2kB ram!

Visa signatur

~. Citera så jag hittar tillbaka .~

Permalänk
Medlem
Skrivet av KeVVa:

De må vara så men variabeln ifrån millis() overflowar själv efter 50 dagar och börjar om ifrån noll enligt dokumentationen. Det är väl bara en petites, och inget som påverkar programmet. Dock så drar det mycket minne!

Koden kommer ifrån arduinos tutorial och där castar de inte, jag castar inte heller i min kod.
http://arduino.cc/en/Tutorial/BlinkWithoutDelay

Edit: En arduino long variabel använder ca. 4 byte. Det var mindre än vad jag trodde. Arduino uno (ATmega328) har 2kB ram!

Låt säga att du jämför mot millis() varje millisekund. När den råkar ut för overflow blir värdet 0. Låt oss säga att du satte previous millisekunden före, värdet på den är alltså (2^32)-1. Vid den tidpunkt då millis slår över till 0, kommer din jämförelse 0-(2^32-1) bli väldigt stort negativt. Det kommer alltså dröja 50 dagar innan din if-sats är sann och det som är i den utförs, eller med maximal otur som i exemplet kommer den aldrig utföras då skillnaden mellan millis och previous aldrig kan bli större än noll.

Om du istället castar resultatet till en osignerad long, som inte kan hålla negativa tal kommer det stora negativa talet (som har sin mest signifikanta bit 1) att betraktas som ett mycket stort positivt tal, med andra ord kommer if-satsen att vara sann och previous kommer att "följa med" värdet på millis. Den enda störningen är att förväntad fördröjning kan bli något kortare.

Så, även om det kan betraktas som en petitess är det en väldigt enkel sak att fixa.

Permalänk
Medlem
Skrivet av reinholdsson:

Låt säga att du jämför mot millis() varje millisekund. När den råkar ut för overflow blir värdet 0. Låt oss säga att du satte previous millisekunden före, värdet på den är alltså (2^32)-1. Vid den tidpunkt då millis slår över till 0, kommer din jämförelse 0-(2^32-1) bli väldigt stort negativt. Det kommer alltså dröja 50 dagar innan din if-sats är sann och det som är i den utförs, eller med maximal otur som i exemplet kommer den aldrig utföras då skillnaden mellan millis och previous aldrig kan bli större än noll.

Om du istället castar resultatet till en osignerad long, som inte kan hålla negativa tal kommer det stora negativa talet (som har sin mest signifikanta bit 1) att betraktas som ett mycket stort positivt tal, med andra ord kommer if-satsen att vara sann och previous kommer att "följa med" värdet på millis. Den enda störningen är att förväntad fördröjning kan bli något kortare.

Så, även om det kan betraktas som en petitess är det en väldigt enkel sak att fixa.

Tack för en utförlig förklaring - Tanke inte så långt!

Men vi ändrar ju previousMillis i varje loop. Så egentlige kan man väl bara fastna i en iteration och inte i en lång loop på 50 dagar! Eller har jag fortfarande fel?

Visa signatur

~. Citera så jag hittar tillbaka .~

Permalänk
Medlem
Skrivet av KeVVa:

Tack för en utförlig förklaring - Tanke inte så långt!

Men vi ändrar ju previousMillis i varje loop. Så egentlige kan man väl bara fastna i en iteration och inte i en lång loop på 50 dagar! Eller har jag fortfarande fel?

Det är denna kod jag syftar på,

if(currentMillis - previousMillis > interval) { previousMillis = currentMillis; //spela musik här }

previousMillis ändras endast när skillnaden currentMillis - previousMillis är större än interval, vilket enligt tidigare beskrivning i värsta fall kommer ske först efter 50 dagar.

Permalänk
Medlem
Skrivet av reinholdsson:

Det är denna kod jag syftar på,

if(currentMillis - previousMillis > interval) { previousMillis = currentMillis; //spela musik här }

previousMillis ändras endast när skillnaden currentMillis - previousMillis är större än interval, vilket enligt tidigare beskrivning i värsta fall kommer ske först efter 50 dagar.

Oj då! Märkte inte det själv. Där har du helt rätt - den raden ska självklart ligga under if-satsen!

if(currentMillis - previousMillis > interval) { //spela musik här } previousMillis = currentMillis;

Visa signatur

~. Citera så jag hittar tillbaka .~

Permalänk
Medlem

Om du inte har en fördröjning större än interval någon annanstans kommer if-satsen aldrig vara sann, och har du det kommer den alltid att vara det. Du tänkte rätt från början, men som jag tidigare beskrivit togs ingen hänsyn till overflow.

Permalänk

Jag är oerhört tacksam för all hjälp! Fick allting att fungera precis så som jag ville Men mycket vill ha mer...

Har en kanal på min RC sändare som inte används, en flip-switch. Så jag tänkte använda den för att trigga en specifik låt.

När jag skrivit denna kod:

int ch5; // hold the value void setup(){ pinMode(9, INPUT); Serial.begin (9600); } void loop(){ ch5 = pulseIn(9, HIGH, 25000); Serial.print(" Channel "); Serial.println(ch5); delay(200); }

Då får jag fram ett värde som jag klart och tydligt kan läsa av i serial monitoren, och som slår om när ja slår om brytaren.

Så jag implementerade den koden i min andra kod, och körde en "if" för att det skulle triggas.

Såhär ser det ut:

//Test med Arduino och MP3 Trigger för att automatisera ljudet// #define trigPin 2 #define echoPin 3 #include <MP3Trigger.h> MP3Trigger trigger; long previousMillis = 0; long interval = random(5000,10000); //Anger väntetiden mellan randomljuden. //////////////////////////////////// void setup() { Serial.begin (9600); trigger.setup(); pinMode(trigPin, OUTPUT); pinMode(echoPin, INPUT); } ////////////////////////////////// void loop() { int duration, distance; digitalWrite(trigPin, LOW); delayMicroseconds(2); digitalWrite(trigPin, HIGH); delayMicroseconds(10); digitalWrite(trigPin, LOW); duration = pulseIn (echoPin, HIGH); distance = (duration/2) /29.1; //Serial.print (distance); //Serial.print ("cm "); //delay(100); if (distance < 30) // Numret avger vid vilket avstånd i centimeter det ska triggas på. {trigger.play(1); delay(2500); //Väntetid tills hummen börjar. trigger.play(random(2,8)); delay(2500);} int ch5; ch5 = pulseIn(9, HIGH, 25000); Serial.print(" "); Serial.println(ch5); if (ch5<1500); { trigger.play(9); delay(500); } unsigned long currentMillis = millis(); if(currentMillis - previousMillis > interval) { previousMillis = currentMillis; trigger.play(random(10,46)); //Vilka ljud den ska slumpa fram. }}

Och det är den fet-markerade delen där då som inte fungerar. Den triggar ljudet, men gör det om och om och om igen. Den verkar inte få ett korrekt värde. Och det som printas ut i monitoren ser ut såhär: "%¤%¤%¤%¤%¤%¤%¤%¤%¤%¤%¤!¤1¤1¤ñ1¤ñ¤!¤1¤1¤1¤1¤%¤%¤%¤%¤%¤%¤%¤õ%¤%¤%¤". Man kan se i mönstret vart jag slår om brytaren, men det är ändå ingen signal som verkar vettig. Varken för mig eller min Arduino.

Jag har säkert gjort ett jättestort rookie-misstag, det är jag helt bombis på, iom att det är första gången jag kodar.. någonsin! Men jag har googlat och inte lyckats få fram ett svar Så jag vänder mig återigen hit, och hoppas att alla ni duktiga kodare kan hjälpa mig!

Tack på förhand!

Visa signatur

Details is everything, the rest is just details.

[Bygglogg] Fullskalig radiostyrd R2D2: https://www.sweclockers.com/galleri/11953-radiostyrd-r2d2-byg...

Permalänk
Medlem
Skrivet av DeepSilence:

Jag är oerhört tacksam för all hjälp! Fick allting att fungera precis så som jag ville Men mycket vill ha mer...

Har en kanal på min RC sändare som inte används, en flip-switch. Så jag tänkte använda den för att trigga en specifik låt.

När jag skrivit denna kod:

int ch5; // hold the value void setup(){ pinMode(9, INPUT); Serial.begin (9600); } void loop(){ ch5 = pulseIn(9, HIGH, 25000); Serial.print(" Channel "); Serial.println(ch5); delay(200); }

Då får jag fram ett värde som jag klart och tydligt kan läsa av i serial monitoren, och som slår om när ja slår om brytaren.

Så jag implementerade den koden i min andra kod, och körde en "if" för att det skulle triggas.

Såhär ser det ut:

//Test med Arduino och MP3 Trigger för att automatisera ljudet// #define trigPin 2 #define echoPin 3 #include <MP3Trigger.h> MP3Trigger trigger; long previousMillis = 0; long interval = random(5000,10000); //Anger väntetiden mellan randomljuden. //////////////////////////////////// void setup() { Serial.begin (9600); trigger.setup(); pinMode(trigPin, OUTPUT); pinMode(echoPin, INPUT); } ////////////////////////////////// void loop() { int duration, distance; digitalWrite(trigPin, LOW); delayMicroseconds(2); digitalWrite(trigPin, HIGH); delayMicroseconds(10); digitalWrite(trigPin, LOW); duration = pulseIn (echoPin, HIGH); distance = (duration/2) /29.1; //Serial.print (distance); //Serial.print ("cm "); //delay(100); if (distance < 30) // Numret avger vid vilket avstånd i centimeter det ska triggas på. {trigger.play(1); delay(2500); //Väntetid tills hummen börjar. trigger.play(random(2,8)); delay(2500);} int ch5; ch5 = pulseIn(9, HIGH, 25000); Serial.print(" "); Serial.println(ch5); if (ch5<1500); { trigger.play(9); delay(500); } unsigned long currentMillis = millis(); if(currentMillis - previousMillis > interval) { previousMillis = currentMillis; trigger.play(random(10,46)); //Vilka ljud den ska slumpa fram. }}

Och det är den fet-markerade delen där då som inte fungerar. Den triggar ljudet, men gör det om och om och om igen. Den verkar inte få ett korrekt värde. Och det som printas ut i monitoren ser ut såhär: "%¤%¤%¤%¤%¤%¤%¤%¤%¤%¤%¤!¤1¤1¤ñ1¤ñ¤!¤1¤1¤1¤1¤%¤%¤%¤%¤%¤%¤%¤õ%¤%¤%¤". Man kan se i mönstret vart jag slår om brytaren, men det är ändå ingen signal som verkar vettig. Varken för mig eller min Arduino.

Jag har säkert gjort ett jättestort rookie-misstag, det är jag helt bombis på, iom att det är första gången jag kodar.. någonsin! Men jag har googlat och inte lyckats få fram ett svar Så jag vänder mig återigen hit, och hoppas att alla ni duktiga kodare kan hjälpa mig!

Tack på förhand!

Ser ut som om du har fel frekvens på baud rate:en i serial monitorn. Prova lägg en Serial.println(""); med någon nyttig text i, i din setup.
Vad fick du för värden i din lilla sketch på pulseIn(9, HIGH, 25000); ?

Visa signatur

~. Citera så jag hittar tillbaka .~

Permalänk
Skrivet av KeVVa:

Ser ut som om du har fel frekvens på baud rate:en i serial monitorn. Prova lägg en Serial.println(""); med någon nyttig text i, i din setup.
Vad fick du för värden i din lilla sketch på pulseIn(9, HIGH, 25000); ?

Jo jag tyckte också det såg ut som så, men baud rate:en ser ut att vara samma.
Testade att lägga in "Hello World", men får samma resultat :/

Värdena som jag får med den andra koden är 1940-1948 när den är avslagen, och 1217-1224 när den är påslagen.
Testade i den koden att lägga in:

if (ch5<1500); { Serial.print ("On"); } else { Serial.print ("Off"); }

Och den funkar klockrent. Visar "Off" när brytaren är av, och visar "On" när jag slår på den.

Men nu när jag satt här och testade lite medan jag skrev det här svaret så löste jag det.. När jag tog bort semikolon efter "if (ch5<1500)" så funkar allting precis som jag vill!

Tack för all hjälp och snabba svar!

Visa signatur

Details is everything, the rest is just details.

[Bygglogg] Fullskalig radiostyrd R2D2: https://www.sweclockers.com/galleri/11953-radiostyrd-r2d2-byg...