Zonnetracker vollop benut

Toon hier Uw afgeronde projecten aan anderen.
Gebruikers-avatar
Berichten: 256
Geregistreerd: 05 Apr 2018, 00:44
Woonplaats: ALKMAAR

Re: Zonnetracker vollop benut

Berichtdoor Gompy » 10 Sep 2019, 16:59

Leuker kunnen we het niet maken, maar "slimmer: word ik wel :D :lol: :D 8-)

Dat de hele nacht terug draaien zal ik maar niet doen want als de buurvrouw met open ramen slaapt dan heeft ze natuurlijk daar ook weer last van.

Nu de monitor nog want ik kan die het echt niet volgen zo snel als die over het beeld scrolled :roll:
Ik denk dat een update gelijk aan unsigned long interval = 60000 meer dan genoeg is.

Dus nu komt de volgende vraag, zou een aparte void serialmonitor(); misschien kunnen ?

De delayfunctie met potmeter schrijf ik eruit en wil daar een monitor voor de zonnepaneel stroom voor in de plaats zetten.
Ik heb een module liggen voor de stroom, een 20Ampere, dus die zou heel goed op de plaats van de potmeter gezet kunnen worden.

Ter aanvulling: ik wil de gehele elektronica van het paneel in de winter gaan vernieuwen.

Advertisement

Gebruikers-avatar
Berichten: 256
Geregistreerd: 05 Apr 2018, 00:44
Woonplaats: ALKMAAR

Re: Zonnetracker vollop benut

Berichtdoor Gompy » 10 Sep 2019, 22:48

Ik denk (....) dat alles erin staat en werkt, tenminste op het bureau.
De serialloop staat nu op 10 seconden omdat 30 minuten oid even te lang is om te monitoren.

Schiet maar als er iets fout is 8-)

Code: Alles selecteren
/*
 * IN AND OUTPUTS Arduino (nano)
 * A0 = tr - input LDR top right
 * A1 = br - input LDR bototm right
 * A2 = tl - input LDR top left
 * A3 = bl - input LDR bottom left
 * A4 = input sda LCD 4x20
 * A5 = input sdc LCD 4x20
 * A6 = input potentiometer 10k tolerange between all LDR's
 * A7 = input potentiometer 10k (not used now)
 * D9 = in1 - outnput L298N - motor left/right
 * D10 = in2 - output L298N - motor left/right
 * D11 = in3 - output L298N -motor up/down
 * D12 = in4 - output L298N - motor up/down
 *
 * SHORTCUTS IN SKETCH
 * avt = average top LDR's tl and tr
 * avb = average bottom LDR's bl and br
 * avl = average left LDR's tl and bl
 * avr = average right LDR's tr and br
 * dv = differenge vertical LDR's avt and avb
 * dh = difference horizontal LDR's avl and avr
 */

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
 
LiquidCrystal_I2C lcd(0x27,20,4); // LCD BLUE
// LiquidCrystal_I2C lcd(0x3F,20,4); // LCD GREEN
 
//  MOTOR AZIMUTH
int in1 = 9;  // D9 output to in1 L298N module
int in2 = 10; // D10 output to in2 L298N module

// MOTOR ELEVATION
int in3 = 11; // D11 output to in3 L298N module
int in4 = 12; // D12 output to in4 L298N module

// NEEDED FOR THE ASYNCHRONOUS TIMER
unsigned long currentMillis;    // Current time
unsigned long previousMillis;   // Past time
unsigned long interval = 60000; // Interval 1*1000mS*60S=1min
int enableState = HIGH;         // Start with on

// NEEDED FOR SERIALMONITOR
int period = 10000;
unsigned long time_now = 0;

void setup()
{
  Serial.begin(9600); // Initialize the serial port
 
  lcd.begin(); // Initialize the lcd
  lcd.backlight(); // ON

// PIN ASSIGN
  pinMode(in1, OUTPUT); // D9 to module in1 L298N
  pinMode(in2, OUTPUT); // D10 to module in2 L298N
  pinMode(in3, OUTPUT); // D11 to module in3 L298N
  pinMode(in4, OUTPUT); // D12 to todule in3 L298N
  pinMode(A0, INPUT); // Top left LDR
  pinMode(A1, INPUT); // Top right LDR
  pinMode(A2, INPUT); // Bottom left LDR
  pinMode(A3, INPUT); // Bottom right LDR
  pinMode(A6, INPUT); // Potentiometer reading tolerance LDR's
  pinMode(A7, INPUT); // Potentiometer reading looptime NOT USED NOW
}
 
void loop()
{
// ROUTINE FLAG TO RUN ASYNCHONE TIMER
  currentMillis = millis(); // Set time on
  if ( currentMillis - previousMillis >= interval)
 {
// HAS TIME PASSED ?
  previousMillis = currentMillis; // Remember last value
  if ( enableState == HIGH)
  {
// IS STATE ON ?
  interval = 1800000; // New interval off time 30min (1*1000*60*30)
  enableState = LOW; // Set state off
  }
  else
  {
// IS STATE OFF ?
  interval = 60000; // New value interval on 1min
  enableState = HIGH; // Set state on
  }
}
 
// LDR LIGHT SENSORS
  int tr = analogRead(A0); // LDR top right
  int br = analogRead(A1); // LDR bottom right
  int tl = analogRead(A2); // LDR top left
  int bl = analogRead(A3); // LDR bottom left
   
// SET TOLERANCE SENSORS 0 - 50
  int tolerance = analogRead(A6)/20.48; // Difference 50 between sensors
   
// SET AVERAGE VALUE LDR'S
  int avt = (tr + tl) / 2; // Average value top
  int avb = (bl + br) / 2; // Average value down
  int avl = (tl + bl) / 2; // Average value left
  int avr = (tr + br) / 2; // Average value right
// AVERAGE DIFFERENCE OF TOP AND BOOTM LIGHT SENSORS
  int dv = avt - avb;
// AVERACE DIFFERENCE OF LEFT AND RIGHT LIGHT SENSORS
  int dh = avl - avr;

// PRINT ONES A MINUTE DEBUG INFORMATION
{
  if(millis() > time_now + period){
  time_now = millis();

// PRINT VALUES SERIAL MONITOR
  Serial.println("********************");
  Serial.print("Top Left\t");
  Serial.print(tl);
  Serial.println();
  Serial.print("Top Right\t");   
  Serial.print(tr);
  Serial.println();
  Serial.print("Bottom Left\t");
  Serial.print(bl);
  Serial.println();
  Serial.print("Bottom Right\t");
  Serial.print(br);
  Serial.println();
  Serial.println();
  Serial.print("Tolerance\t");
  Serial.print(tolerance);
  Serial.println();
  Serial.println();
  Serial.print("+UP<>DOWN-\t");
  Serial.print(dv);
  Serial.println();
  Serial.print("AVT - up\t");
  Serial.print(avt);
  Serial.println();
  Serial.print("AVB - down\t");   
  Serial.print(avb);
  Serial.println();
  Serial.println();
  Serial.print("+WEST<>EAST-\t");
  Serial.print(dh);
  Serial.println();
  Serial.print("AVL - west\t");     
  Serial.print(avl);
  Serial.println();
  Serial.print("AVR - east\t");     
  Serial.print(avr);
  Serial.println();
  Serial.println();
  Serial.println("ELEVATION MOTOR DOWN\t");
  Serial.print(avt < avb);
  Serial.println();
  Serial.println("ELEVATION MOTOR UP\t");
  Serial.print(avt > avb);
  Serial.println();
  Serial.println("ELEVATION MOTOR STOP\t");
  Serial.print(-1*tolerance < dv || dv < tolerance);
  Serial.println();
  Serial.println("ELEVATION MOTOR NIGHT\t");
  Serial.print(avt < 150 && avb < 150);
  Serial.println();
  Serial.println("AZIMUTH   MOTOR WEST\t");
  Serial.print(avr < avl);
  Serial.println();
  Serial.println("AZIMUTH   MOTOR EAST\t");
  Serial.print(avr > avl);
  Serial.println();
  Serial.println("AZIMUTH   MOTOR STOP\t");
  Serial.print(-1*tolerance < dh || dh < tolerance);
  Serial.println();
  Serial.println("AZIMUTH   MOTOR NIGHT\t");
  Serial.print(avr < 150 && avl < 150);
  Serial.println();
  }


  if (-1*tolerance > dv || dv > tolerance) // check difference in top/bottom LIGHT SENSORS is greater than tolerance
{
// CHANGE MOTOR DIRECTION
  if (avt < avb) // If average LIGHT SENSOR values on top side are smaller than on bottom side then elevation motor rotates CLOCKWISE
  {
// SET ELEVATION MOTOR DOWN
  digitalWrite(in3, HIGH && enableState);
  digitalWrite(in4, LOW);
  lcd.setCursor(0,0);
  lcd.print("ELEVATION :  DOWN "); // print lcd row 1
  }
  else // If average LIGHT SENSOR values on bottom side are greater than on top side then elevation motor rotates COUNTERCLOCKWISE
  {
// SET ELEVATION MOTOR UP
  digitalWrite(in3, LOW);
  digitalWrite(in4, HIGH && enableState);
  lcd.setCursor(0,0);
  lcd.print("ELEVATION :    UP ");// Print lcd row 1
  }
}
  else if (-1*tolerance < dv || dv < tolerance) // If difference is smaller than tolerance, STOP elevation motor
  {
// STOP ELEVATION MOTOR
  digitalWrite(in3, LOW);
  digitalWrite(in4, LOW);
  lcd.setCursor(0,0);
  lcd.print("ELEVATION :  STOP "); // Print lcd row 1
 
// MOVE ELEVATION MOTOR NIGHT POSITION
  if (avt < 150 && avb < 150) // Sensor value
  {
  digitalWrite(in3, HIGH);
  digitalWrite(in4, LOW);
  lcd.setCursor(0,0);
  lcd.print("ELEVATION :  NIGHT"); // Print lcd row 1
  }
}
 
  if (-1*tolerance > dh || dh > tolerance) // Check difference in left and right LIGHT SENSORS is within tolerance range
 {
// CHANGE MOTOR DIRECTION
  if (avr < avl) // If average LIGHT SENSOR values on left side are greater than right side, azimuth motor rotates CLOCKWISE
  {
// SET AZIMUTH MOTOR WEST = LEFT
  digitalWrite(in1, HIGH && enableState);
  digitalWrite(in2, LOW);
  lcd.setCursor(0,1);
  lcd.print("AZIMUTH   :  WEST "); // Print lcd row 2
  }
   else // If average LIGHT SENSOR values on right side are greater than on left side, azimuth motor rotates COUNTERCLOCKWISE
  {
// SET AZIMUTH MOTOR EAST = RICHT
  digitalWrite(in1, LOW);
  digitalWrite(in2, HIGH && enableState);
  lcd.setCursor(0,1);
  lcd.print("AZIMUTH   :  EAST "); // Print lcd row 2
  }
 }
  else if (-1*tolerance < dh || dh < tolerance) // If difference is smaller than tolerance, STOP azimuth motor
  {
// STOP AZIMUTH MOTOR
  digitalWrite(in1, LOW);
  digitalWrite(in2, LOW);
  lcd.setCursor(0,1);
  lcd.print("AZIMUTH   :  STOP "); // Print lcd row 2
  }
 
// MOVE AXIMUTH MOTOR NIGHT POSITION / RIGHT
  if ((avr < 150) && (avl < 150))  // Sensorvalue
  {
  digitalWrite(in1, LOW);
  digitalWrite(in2, HIGH);
  lcd.setCursor(0,1);
  lcd.print("AZIMUTH   :  NIGHT"); // Print lcd row 2
  }
 {
 
// PRINT TOLERANCE LCD ROW 4
  lcd.setCursor(0,3);
  lcd.print("TOLERANCE : ");
  char temp1[5]; // Enough spaces for 4 numbers
  snprintf(temp1,6, "%5d", tolerance); // %4d = 4 digets, right aligned
  lcd.print(temp1);
  lcd.setCursor(18, 3);
  lcd.print("+-");

  delay(300);//
  }
}
 
void print2digits(int number)
{
  if (number >= 0 && number < 10)
  {
    Serial.write('0');
  }
  Serial.print(number);
}

Gebruikers-avatar
Berichten: 256
Geregistreerd: 05 Apr 2018, 00:44
Woonplaats: ALKMAAR

Re: Zonnetracker vollop benut

Berichtdoor Gompy » 11 Sep 2019, 15:26

@ Gij Kieken (of iemand anders die het antwoord weet),

Volgens de serial monitor wordt de loop tijd niet gereset, klopt dat ?
Ik zie alleen maar de waarde oplopen van currentMillis en previousMillis en dat worden gigantische waarden.
Mijn gevoel zegt me dat na iedere 30 minuten de tijd weer naar 0 gezet moet worden anders komen we nooit meer bij die 6000 uit (....)

Na ruim een uur te hebben gewacht heb ik dus constateren dat de motoren dus maar 1x (na 30 minuten) hebben gedraaid, daarna doet de sketch niets meer :(

Gebruikers-avatar
Berichten: 256
Geregistreerd: 05 Apr 2018, 00:44
Woonplaats: ALKMAAR

Re: Zonnetracker vollop benut

Berichtdoor Gompy » 11 Sep 2019, 17:21

Het viel me op dat twee keer "interval" gebruikt wordt met verschillende waarde, 6000 en 180000.
Dit kan ik dus niet plaatsen.....hoe kan dit en hoe weet de sketch welke hij moet uitvoeren ?

De UP en EAST zouden minstens al 4x moeten draaien omdat de waarden verschillen en dus de motoren het paneel deze kant op zouden moeten sturen, maar er gebeurd werkelijk niets.
Bij starten draaien de motoren voor 1 minuut, na 30 minuten nogmaals en daarna zwijgt alles :?


Code: Alles selecteren
unsigned long currentMillis;    // Current time
unsigned long previousMillis;   // Past time
unsigned long interval = 60000; // Interval 1*1000mS*60S=1min
int enableState = HIGH;         // Start with ON


void loop()
{
// ROUTINE FLAG TO RUN ASYNCHONE TIMER
  currentMillis = millis(); // Set time ON
  if (currentMillis - previousMillis >= interval)
 {
// HAS TIME PASSED ?
  previousMillis = currentMillis; // Remember last value
  if (enableState == HIGH)
  {
// IS STATE ON ?
  interval = 1800000; // New interval OFF time 30min (1*1000*60*30)
  enableState = LOW; // Set state OFF
 }
  else
  {
// IS STATE OFF ?
  interval = 60000; // New value interval ON time for 1 min
  enableState = HIGH; // Set state on
  }
}

Gebruikers-avatar
Berichten: 256
Geregistreerd: 05 Apr 2018, 00:44
Woonplaats: ALKMAAR

Re: Zonnetracker vollop benut

Berichtdoor Gompy » 12 Sep 2019, 12:25

GELUKT !!!

Door mijn fout keek ik naar de verkeerde waarden en door een schijffoutje, welke niet door de compiler gezien werd (....), liep ik vast.
De serialmonitor geeft nu wel de juiste waarden weer zodat ik het proces goed kan volgen en de sketch ook begrijp.
De sketch doet wat hij doen moet, ook buiten op het grote paneel, alleen nog even de waarden aanpassen van looptijd.

De potmeter voor de tijd is verdwenen en op deze vrijgekomen input zal een stroommeetmoduul geplaatst worden.
De potmeter voor de tolerantie heb ik (voorlopig) laten zitten, deze is van belang voor de tijd van het jaar, het type LDR's en de opstelling van deze.
Misschien dat ik in de toekomst deze potmeter er ook uit schrijf en de tolerantie waarde laat aanpassen door de waarde van de LDR's.
In de zomer een grote tolerantie omdat dan het paneel genoeg licht kan pakken en in de winter een kleine omdat dan de licht inval veel kleiner is.

Ik zal, als het volledige schema klaar is, samen met de uitgewerkte / aangepaste sketch hier posten.

Shooter, Koepel, Gij Kieken en degene die ik nog vergeten ben, alle bedankt voor de (morele) steun en jullie vasthoudendheid !

Gebruikers-avatar
Berichten: 631
Geregistreerd: 15 Nov 2015, 11:54

Re: Zonnetracker vollop benut

Berichtdoor Gij Kieken » 12 Sep 2019, 13:31

Nu op naar je belofte ,een flow chart maken en de code opzuiveren.
E.a. kan in functies gezet worden om het overzichtelijker te maken,ook het gebruik van millis doorgronden.
In de loop van tijd kun je misschien problemen krijgen met het geheugen door de vele en frequente Serial.print's.
Zoek eens op Arduino F-macro,,,,
Succes,

Gebruikers-avatar
Berichten: 256
Geregistreerd: 05 Apr 2018, 00:44
Woonplaats: ALKMAAR

Re: Zonnetracker vollop benut

Berichtdoor Gompy » 13 Sep 2019, 11:57

De F-macro.......nog maar even wachten tot ik echt alles begrijp en nieuwe sketches kan schrijven zonder de oeverloze hulp van jullie.
De F-macro zal ik waarschijnlijk ook (nog) niet niet nodig hebben (....) , ik gebruik nu maar 26% van het geheugen met deze sketch.
Zal nog ietjes meer worden voor het stroommeetmoduul, maar ook daarmee verwacht ik niet in de problemen komen met het geheugen.

De sketch is al voor een groot deel opgezuiverd en de flowchart zit eigenlijk in de sketch zelf verwerkt (serialmonitor) en is ook deels zichtbaar op de display.
Maar ik moet nu eerst het elektrisch schema gaan maken zodat mijn nageslacht dat ook begrijpt en eventueel kan repareren/vervangen.
Ik zal waarschijnlijk nooit in mijn korte bestaan nog op deze aardkloot zonnepanelen gaan plaatsen / gebruiken, maar ik denk dat mijn (klein)kinderen ze wel kunnen gebruiken op bv de camping.
Ik wou dat ik deze had toen wij nog kampeerden met de kinderen, wat zou dat een luxe zijn.
Vorig jaar verlichte ik elke avond met kerst de tuin ermee met zeker duizend (LED)lampjes, geen enkel probleem.
Bijlagen
tuin achter 025.JPG
tuin achter 025.JPG (95.18 KiB) 7532 keer bekeken

Gebruikers-avatar
Berichten: 256
Geregistreerd: 05 Apr 2018, 00:44
Woonplaats: ALKMAAR

Re: Zonnetracker vollop benut

Berichtdoor Gompy » 14 Sep 2019, 11:57

De display van de solartracker.
Bijlagen
P1050507.JPG
P1050507.JPG (48.74 KiB) 7513 keer bekeken

Gebruikers-avatar
Berichten: 2655
Geregistreerd: 06 Aug 2016, 01:03

Re: Zonnetracker vollop benut

Berichtdoor Koepel » 15 Sep 2019, 05:06

Netjes hoor :D

Een interval kun je in de sketch wijzigen als je wilt dat de aan-tijd anders is dan de uit-tijd.
Zoals in dit voorbeeld: https://github.com/Koepel/Fun_with_millis/blob/master/millis_different_on_and_off_times.ino.

60000 :

Bij een Arduino Uno of Arduino Mega gebruikt de compiler standaard 16-bit signed integer voor getallen.
De "60000" pas gemakkelijk in een unsigned long, zelfs in een unsigned int, maar niet in een gewone int.
Meestal gaat het goed, maar bij een berekening kan het mis gaan zonder dat het opvalt.
Je kunt de compiler vertellen dat de "60000" een "unsigned long" is door er "UL" achter te zetten (UL van Unsigned Long).
Code: Alles selecteren
unsigned long interval = 60000UL;


Inspringen :

In je sketch kan het het inspringen beter.
Een regel met commentaar kun je ook laten inspringen.

Hieronder een voorbeeld. De code is hetzelfde, ik heb alleen het inspringen, commentaar en lege regels anders gedaan en "UL" aan de grote getallen toegevoegd.
cpp code
void loop()
{
// PUT THE CURRENT VALUE OF MILLIS IN THE currentMillis VARIABLE
currentMillis = millis();

// HAS TIME PASSED ?
if ( currentMillis - previousMillis >= interval)
{
previousMillis = currentMillis; // Remember this moment for the next time

if ( enableState == HIGH)
{
// IS STATE ON ?
interval = 1800000UL; // New interval off time 30min (1*1000*60*30)
enableState = LOW; // Set state off
}
else
{
// IS STATE OFF ?
interval = 60000UL; // New value interval on 1min
enableState = HIGH; // Set state on
}
}


millis() :

Dit:
Code: Alles selecteren
if(millis() > time_now + period){
is niet juist.
Bij gebruik van millis() kun je huidige waarde onthouden, en later kun je "currentMillis - previousMillis" doen. Dan gaat het goed.
Als je iets met een millis() waarde doet, dan is het beter om niet iets er bij op te tellen.

Dus zodra je dit doet: "time_now + period", dan is er een probleem als millis() in de buurt van de 0xFFFFFFFF komt. Dat is 50 dagen na het aanzetten van het Arduino boardje.

Dus eenmaal in de 50 dagen is er een kans dat de interval van het schrijven naar de seriële monitor verkeerd gaat :shock:
Dat geeft natuurlijk niets, maar het gaat om het principe ;)

Kijk nog eens naar de BlinkWithoutDelay: https://www.arduino.cc/en/tutorial/BlinkWithoutDelay hoe het wordt gedaan.
Bij meerdere software timers met millis() krijgt iedere timer een eigen 'previousMillis' en een eigen 'interval'.
Je hebt daar al een 'period' en 'time_now' voor, dus dat is okay.
Ik gebruik graag één 'currentMillis' voor de hele loop(), dus dan wordt het:
Code: Alles selecteren
  // PRINT ONES A MINUTE DEBUG INFORMATION
  if( currentMillis - time_now >= period)
  {
    time_now = currentMillis;

    // PRINT VALUES SERIAL MONITOR
    Serial.println("********************");
    ...

Gebruikers-avatar
Berichten: 2655
Geregistreerd: 06 Aug 2016, 01:03

Re: Zonnetracker vollop benut

Berichtdoor Koepel » 15 Sep 2019, 14:50

De BlinkWithoutDelay heeft de led 1 seconde aan en 1 seconde uit: https://www.arduino.cc/en/tutorial/BlinkWithoutDelay.
Je mag die led 200ms aan en 1 seconde uit doen, door in de sketch de interval te wijzigen.
Dus jouw motor is 3 minuten aan, en daarna 30 minuten uit.

Je mag heel veel software timers maken met millis().
Maar iedere software timer heeft een eigen 'previousMillis' en een eigen 'interval'.
Dus stel dat je een rode en een groene led hebt die onafhankelijk van elkaar knipperen.
Dan krijg je vier variabelen:
Code: Alles selecteren
unsigned long previousMillisGroen;
unsigned long intervalGroen;
unsigned long previousMillisRood;
unsigned long intervalRood;


Ik heb eens 27000 aparte software timers met millis() gemaakt (https://github.com/Koepel/Fun_with_millis/blob/master/millis_overdone.ino). Dan zijn er dus ook 27000 verschillende 'previousMillis' en 27000 verschillende 'interval' variabelen.

Naar het omschakelen van dag en nacht heb ik niet goed gekeken. Ik weet eerlijk gezegd niet zo goed wat ik daar mee aan moet.

VorigeVolgende

Terug naar Afgeronde projecten

Wie is er online?

Gebruikers in dit forum: Geen geregistreerde gebruikers en 1 gast