Allereerste Arduino project - wat kan er beter?

Hallo,

Ik heb een allereerste Arduino projectje gemaakt. Er valt nog HEEL veel te leren, maar ik had dit graag al eens gedeeld en gevraagd wat jullie ervan vinden en wat er allemaal kan verbeterd worden.

Doel:
Arduino bestuurt een servo motor wanneer de HC-SR04 iets detecteert. De servo drukt de record knop in van een GOPRO camera en na een x-tal seconden drukt de servo motor nog eens op de record knop van de GOPRO camera om het uit te zetten.
Er is ook een LCD scherm waarbij wordt weergeveven of de camera aan is of uit.

Opstelling:

Code:

#include <LiquidCrystal.h>
#include <Servo.h>
Servo myservo;
const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
#define trigPin 8
#define echoPin 10

void setup(){
  myservo.attach(9);
  myservo.write(0);
Serial.begin(9600);
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
// set up the LCD's number of columns and rows:
  lcd.begin(16, 2);
  // Print a message to the LCD.
  lcd.setCursor(0, 0);
  lcd.print("Hallo");
}

void loop(){
  
 // lcd.setCursor(0, 1);
  //lcd.print(millis() / 1000);
  int duration, distance;
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(100);
  digitalWrite(trigPin, LOW);
  duration = pulseIn(echoPin, HIGH);
  distance = (duration/2) / 29.1;
  Serial.print(distance);
  Serial.println(" cm");
  int thisPitch = map(distance, 0, 200, 2093, 22);
  tone(4, thisPitch);
  delay(50);
  noTone(4);
  if (distance < 50) {    //Distance in cm
  
  delay(100);
  lcd.setCursor(0, 0);
  lcd.print("Hallo");
  lcd.setCursor(0, 1);
  lcd.print("Camera on");
  
  myservo.write(100);       // angle of the servo arm
  delay (700);
  myservo.write(0);
  delay (10000); 

  delay(100);
  lcd.setCursor(0, 0);
  lcd.print("Hallo");
  lcd.setCursor(0, 1);
  lcd.print("Camera off");
 
  myservo.write(100);       // angle of the servo arm
  delay (700);
  myservo.write(0);
  delay (2000);
  }
}

Hoe krijgt de servo zijn 5 volt? Ik hoop niet door de Arduino heen, want zo'n servo gebruikt veel meer stroom dan het lullige spanningsregelaartje op de Arduino kan leveren.

dat gaat helaas niet werken zo want de imer voor de afstand is dezelfde als die de servo gebruit, dus helaas, verder is het gebruik van delay niet aan te raden, maar verder is het een leuk begin , gebruik wel commentaar dan kun je zelf en anderen lezen wat je bedoelt.

Als je de Arduino via USB voedt, wordt de spannings regelaar niet gebruikt en is er geen probleem wat dat betreft. Limiet is dan in dat geval 500 mA.

Op dit moment wordt de Arduino gevoed via USB.
Als ik het goed begrijp dan gebruikt de Arduino via USB de 5V regulator niet en is er een limiet van 500 mA? En wanneer het via de DC Jack is of via de VIN pin is, dan wordt deze 5V regulator wel gebruikt?

Nu is het de bedoeling dat deze Arduino in de toekomst via een batterij zal moeten worden gevoed. Hiervoor dacht ik aan een 9V en deze aan te sluiten aan de DC Jack.

Hoe kan ik dan best de 5V voorzien voor de servo?

Ik heb iets nieuws uitgetekend. Lijkt jullie dit een goede oplossing?

Hoi rubent, welkom !

Zo'n 9 volt batterij, is in werkelijkheid zes stuks hele kleine batterijtjes die als 2 x 3 in een rechthoekige verpakking zit (vandaar het typenummer 6F22).
Van de zo gemaakte 9 volt, ga jij de helft overboord gooien.
Dat lijkt mij niet heel erg efficiënt, en omdat de interne batterijtjes zo klein zijn zal het blokje sowieso al niet erg lang meegaan.
Dus wellicht dat je het 9 volt blokbatterijtje beter vervangt door een soortgelijke houder als je laat zien voor de servo (die sowieso veel meer stroom zal trekken dan de rest van je installatie, maar minder vaak zal worden aangesproken)

Verder staat er een fout in het schema.
Dat is niet jouw schuld, want die fout zie je bijna overal terug.
De potmeter op de print, die het contrast moet instellen voor de LCD, stuurt een spanning naar de betreffende pin, die afhankelijk van de stand van de potmeter, tussen de 5 volt en de nul volt ligt.
Maar je zult zien dat die altijd aan het eind van je potmeter zal staan, nabij het punt waar nul volt zit.
Als het werkt dan werkt het, maar dit is niet hoe de maker van de LCD het bedoeld heeft.
De verbinding met 5 volt en de potmeter mag je voortaan altijd weglaten.
Want die pin zit in de LCD hardware al aan de 5 volt (via weerstanden), en je moet 'm alleen omlaag trekken, niet omhoog.
Door dat te doen heeft de potmeter ook een beter instelbereik dan het nu heeft.
Jouw code ziet er helemaal niet slecht uit voor het eerste project.
De eerder gegeven commentaren van de vrienden hierboven zijn ook allemaal waar en nuttig.

Uiteraard kan de code ook een heel stuk efficiënter, maar wellicht dat je eerst de code precies laat doen wat je wil.
Dus doet het nu wat jij wil ?
Zo niet, laat dan even weten wat er niet goed gaat.

Wanneer het nu wel goed werkt, dan is het een goed idee om een andere manier te gebruiken voor je timer, je vindt ook in het Nederlandstalige deel een verwijzing (klik !) naar hoe je dat kunt doen.
Verder kun je proberen te voorkomen dat er herhalingen in je code zitten.
Het aanzetten van je GoPro is voor je Arduino exact hetzelfde als het uitzetten ervan.
Dus dat kun je met 1 deel van je code doen door dat in wat heet een functie te zetten.
Aangezien je code er nu al goed uitziet, is het een goed idee eens te kijken of je ook met functies kunt leren programmeren want daar ga je in de toekomst veel plezier van hebben.

Hey!
Heel erg bedankt en ontzettend fijn dat jullie me helpen... ontzettend leerrijk!
Ik heb het schema aangepast door de 5V naar de potentiometer weg te laten. Is dat wat u bedoelde? Niet letten op die stippellijnen, dat is een bug dat ik niet weg krijg.

De code doet wat het moet doen, maar omdat ik nog niet weet hoe functies werken heb ik gebruik gemaakt van een delay. Ik zou eigenlijk willen dat de GoPro opneemt wanneer er beweging wordt gedetecteerd door de sensor en de GoPro stopt met opnemen wanneer er geen beweging meer is.

Ah, OK.

Dan doet de code dus ongeveer wat jij wil en niet precies.
Want de code stopt het opnemen na 10 seconden, beweging of niet.
Ik meen te begrijpen dat jij alles wil opnemen zolang er iets gedetecteerd wordt.
Je kijkt nu tot je 1 keer een beweging ziet, en neemt dan 10 seconden op.
Daarna kijk je pas weer of er beweging is, omdat de functie 'loop' dan opnieuw begint.
Je wil dus tijdens het wachten ook nog kijken of er een object detecteerbaar is.
Dan kun je telkens een seconde ofzo wachten en dan even kijken of er nog wat gedetecteerd wordt.
Het meest efficiënt gebeurt dat op de wijze die in de eerder gegeven link gedemonstreerd word.
Maar je kunt ook een teller maken die tot tien telt.
Terwijl die teller loopt, kijk je of er een object te zien is.
Als dat niet zo is, kan de teller eentje hoger worden.
Maar wanneer dat wel zo is, dan moet de teller gereset worden naar nul.
Op die wijze zul je net zo lang opnemen, als het object detecteerbaar is (plus 10 seconden).
Dat is even proberen, maar mag geen al te groot probleem zijn om de realiseren voor jou.

Oh nog iets over efficiëntie:
Je schrijft telkens "Hallo" op de eerste regel van je LCD.
Maar dat staat daar al, dus hoef je niet telkens opnieuw te doen (een LCD aansturen is een relatief langdurige zaak voor een Arduino).

Hetzelfde geldt voor regel 1, de tweede regel voor jou.
"Camera o" hoef je niet opnieuw te schrijven, want dat staat daar al.
De "n" en de "ff" moet je wel bij elke verandering schrijven.

Sterker nog: wanneer je meer dan 1 keer de camera bediend hebt, staat er bij de 2e keer inschakelen, deze tekst op de 2e regel:
"Camera onf".
Dat was ongetwijfeld niet de bedoeling, en dus zul je iets moeten bedenken om die 2e f te wissen wanneer van toepassing.

Zoals je ziet, laat ik graag jouw radertjes in het hoofd ook nog een beetje draaien.

Ik heb de code wat aangepast.
De f character is weggewerkt wanneer het van off naar on gaat.
Op de onderste lijn van het LCD scherm heb ik nu weerstation gezet. In de toekomst wil ik hier een temperatuur en luchtvochtigheid laten verschijnen.

Voor het bedienen van de servo heb ik nog geen functie gevonden. Wordt dit met een for loop gedaan?

#include <LiquidCrystal.h>
#include <Servo.h>
Servo myservo;
const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
#define trigPin 8
#define echoPin 10

void setup(){
  myservo.attach(9);    // attaches the servo on pin 9 to the servo object
  myservo.write(0);      // tell servo to go to position 0
Serial.begin(9600);
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
  lcd.begin(16, 2);   // set up the LCD's number of columns and rows:
  lcd.setCursor(0, 1);
  lcd.print("Weerstation");   // Print a message to the LCD.
}

void loop(){
  int duration, distance;
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(100);
  digitalWrite(trigPin, LOW);
  duration = pulseIn(echoPin, HIGH);
  distance = (duration/2) / 29.1;
  Serial.print(distance);
  Serial.println(" cm");
  int thisPitch = map(distance, 0, 200, 2093, 22);
  tone(4, thisPitch);
  delay(50);
  noTone(4);
  
  if (distance < 5) {    //Distance in cm
  lcd.setCursor(13,0);
  lcd.print(" ");         //Erasing the f character
    lcd.setCursor(4, 0);
  lcd.print("Camera on");
  myservo.write(100);       // angle of the servo arm
  delay (700);
  myservo.write(0);
  delay (10000); 
  lcd.setCursor(4, 0);
  lcd.print("Camera off");
   myservo.write(100);       // angle of the servo arm
  delay (700);
  myservo.write(0);
  delay (2000);
  }
}

Hoi.

Je hebt inderdaad het probleem met de hangende "f" opgelost, maar daardoor is de efficientie niet erg verbeterd, het ziet er meer uit als een patch (code toegevoegd om een fout in de code op te lossen).
In plaats van eerst naar een positie te springen, daar wat te wissen en dan weer terug te springen om grotendeels bestaande tekst opnieuw af te drukken kan het dus efficiënter.
Je kunt ook "n " en "ff" vanaf positie 12 afdrukken.
"n " is dus een n met een spatie er achter.
Uiteraard moet je dan wel eerder in de sketch nog "Camera off" eenmalig naar de LCD sturen, ik ga ervan uit dat dat de begin toestand is.

Ik krijg mogelijk allerlei puristen achter me aan, maar als je de code als een pagina met tekst ziet, dan zou een functie een alinea zijn.
Wellicht beter is het een hoofdstuk uit een boek.

In jouw code zitten ook al zulke functies.
Die heten setup() en loop(), en ze worden beschreven als een void.
Die noem je dus geen voids (== leegte) wanner je daar iets over wil vragen of mededelen, maar functie die niets verwachten te krijgen en ook niets teruggeven, vandaar deze leegtes.
Bij andere functies moet aangegeven worden wat voor soort data ze moeten verwerken.
Een functie (klik voor een Engelstalige uitleg over functies) moet aangeroepen worden, maar de functies die je nu al hebt worden al automatisch aangeroepen door de compiler in de Arduino Editor en hoeven daarom niet meer aangeroepen te worden.
Onderstaand stukje is een geknipt stukje uit jouw code, maar nu als een eigen functie met de naam ToggleOnOff.
Jij moet 'm dan aanroepen met zijn naam: ToggleOnOff()
Wanneer je code vaker gebruikt, is het zinvol om te overwegen er een functie voor te bouwen.
Dat helpt je het overzicht te houden, zeker wanneer de code groter wordt.

void ToggleOnOff(){
  myservo.write(100);       // angle of the servo arm
  delay (700);
  myservo.write(0);
}

Hey,
Heel erg bedankt voor alle tips, het is ontzettend leerrijk en een fantastische hulp :pray:
Ik heb de code lichtjes gewijzigd.
Nu is het nog zoeken naar een correcte methode voor het bedienen van de servo. De radertjes zijn overuren aan het doen en proberen te processen wat je hier allemaal neerschreef, maar momenteel nog zonder een werkende code.

#include <LiquidCrystal.h>
#include <Servo.h>
Servo myservo;
const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
#define trigPin 8
#define echoPin 10

void setup(){
  myservo.attach(9);    // attaches the servo on pin 9 to the servo object
  myservo.write(0);      // tell servo to go to position 0
Serial.begin(9600);
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
  lcd.begin(16, 2);   // set up the LCD's number of columns and rows:
  lcd.setCursor(4, 0);
  lcd.print("Camera off");
  lcd.setCursor(0, 1);
  lcd.print("Weerstation");   // Print a message to the LCD.
}

void loop(){
  int duration, distance;
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(100);
  digitalWrite(trigPin, LOW);
  duration = pulseIn(echoPin, HIGH);
  distance = (duration/2) / 29.1;
  Serial.print(distance);
  Serial.println(" cm");
  int thisPitch = map(distance, 0, 200, 2093, 22);
  tone(4, thisPitch);
  delay(50);
  noTone(4);
  
  if (distance < 5) {    //Distance in cm
  lcd.setCursor(12, 0);
  lcd.print("n ");
  myservo.write(100);       // angle of the servo arm
  delay (700);
  myservo.write(0);
  delay (10000); 
  lcd.setCursor(12, 0);
  lcd.print("ff");
   myservo.write(100);       // angle of the servo arm
  delay (700);
  myservo.write(0);
  delay (2000);
  }
}

Ik heb geprobeerd om de Blink without a delay eens toe te passen op de servo, maar dit lijkt niet te werken

#include <Servo.h>
Servo myservo;
int servoState = 0;           // servo position 0             
unsigned long previousMillis = 0;   
const long interval = 10000;        

void setup(){
  myservo.attach(9);    // attaches the servo on pin 9 to the servo object
  myservo.write(servoState);      // tell servo to go to position 0
  
}

void loop(){
  unsigned long currentMillis = millis(); 
      if (currentMillis - previousMillis >= interval){    
      currentMillis = previousMillis;                     
  
   if (servoState = 0) {    
   servoState = 100;
   
  } else {
    servoState = 0;
  }

myservo.write(servoState);

   }
}

Werkt de servo nu niet meer ?

Ah, ik zie het denk ik al.
In de vorige forumsoftware was het mogelijk een handtekening te maken, bij deze software niet meer.
In mijn handtekening stond een link naar de Nederlandse sectie, maar ook de vraag of alle GNDs wel met elkaar zijn verbonden.

Met andere woorden: de batterij van de servo, en de batterij voor de Arduino moeten met de min (zwarte draad) aan elkaar liggen.
De min (eigenlijk nul volt potentiaal) is het gemeenschappelijke (referentie) punt.
Alle signalen die je gebruikt, worden vergeleken met dat referentiepunt.
Wanneer je de minnen niet aan elkaar koppelt, heeft het ook geen zin om waardes naar de servo te sturen, want dan worden ze niet gezien.
En omdat dat zo niet in je schema staat, denk ik ook dat dit de oorzaak van je probleem is.
Wanneer je ook zo'n breadboard (dat gaatjes bord waar je de draadjes in zou prikken) gebruikt, dan zijn de bovenste en de onderste rode lijnen en de bovenste en onderste zwarte of blauwe lijnen niet me elkaar verbonden.
En wanneer de lijnen in het midden onderbroken zijn, zijn de bijbehorende gaatjes ook niet met elkaar verbonden.
Dus ook even goed kijken naar de afbeeldingen op dat breadboardje.

De servo doet niets wanneer ik die proefcode (blink without a delay maar dan met een servo) laad in de Arduino. Wanneer ik dan weer de andere code laad in de Arduino, dan doet de servo het wel weer.
Is die code zonder de delay, die ik als laatste had gepost, correct?

Het schema moet inderdaad nog wat aangepast worden. In realiteit werkt het wel. Het werkt nu op de 5V van de Arduino die gevoed is via USB.

De code met de servo zonder delay heb ik nu kunnen laten werken, de foutjes zijn weggewerkt.
Nu zou ik dit nog moeten kunnen integreren in het programma dat ik wil voor het bedienen van mijn GoPro. Hier zit ik wel nog vast hoe eraan te beginnen.

#include <Servo.h>
Servo myservo;
const int servoPin = 9;
int servoValue = 0;           // servo position 0             
unsigned long previousMillis = 0;   
const long interval = 2000;        

void setup(){
  myservo.attach(servoPin);    // attaches the servo on pin 9 to the servo object
  myservo.write(servoValue);      // tell servo to go to position 0
  }

void loop(){
  unsigned long currentMillis = millis(); 
      if (currentMillis - previousMillis >= interval){    
      previousMillis = currentMillis;                     
  
   if (servoValue == 0) {    
   servoValue = 100;
   
  } else {
    servoValue = 0;
  }
myservo.write(servoValue);
   }
}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.