Arduino Smooting adc0 en adc1 ADS1115


blackdog

Golden Member

Hi,

Even iets heel anders...
Vanavond stopte de Arduino IDE er mee, ik sloot wat versies af met code die ik nog open had staan, en daarna starte hij niet meer op.
Herinstallatie gedaan, werkt niet.

Dus iemand van jullie die dit probleem kent?

Dank en groet,
Bram

Waarheden zijn "Illusies waarvan men vergeten is dat het illusies zijn"

Gisteren precies hetzelfde voorgehad bij IDE 1.8.12 en W10.

Volgens internet is een file corrupt geworden.

In de map C:\Users\%gebruikersnaam\AppData\Local\Arduino15

Verwijder (of hernoem)
library_index.json en/of
package_index.json.

In mijn geval moest ik package_index.json verwijderen.

Mijn thuis is waar mijn Weller staat
blackdog

Golden Member

Hi Pertinax, :)

Dank voor de tip, deze werkt alleen niet bij mij.

Ik heb al vele opschoon acties gedaan om alle residu van Arduino te verwijderen en schoon te beginnen, geen resultaat.

Op het forum van Arduino.cc loopt een topic hierover maar er is nog geen zinnige reactie van de heren van Arduino.

Even afwachten maar...

Groet,
Bram

Waarheden zijn "Illusies waarvan men vergeten is dat het illusies zijn"

@blackdog:

Volgens mij meet je temperaturen, en die veranderen op een tijdschaal van seconden. Je sampled 860 keer per seconde op de ADS1115.

Dus als het goed is heb je ruim 1000 samples die (ongeveer) hetzelfde zijn. Met AnalogSmooth middel je er hooguit 100.

Ik heb zelf goede ervaring met een exponentieel gemiddelde. deKees poste al code die met een /N werkt. Ik gebruik meestal een N die een macht van 2 is, zodat je met een bitshift kunt werken.

c code:


inline uint16_t exp_average(uint16_t avg, uint16_t val) {
	avg -= ((avg >> 6) & 0x3FF);
	avg += val;
	return avg;
}

Dit is met een deeltal van 64 (die (avg >> 6) deelt door 26), en specifiek voor de arduino/AVR ADC (die 10 bits is (vandaar de 0x3FF).

Dit geeft een trage meting (je hebt zo'n 750 samples nodig om 16-bits nauwkeurigheid te krijgen, i.e. hetzelfde effect als 64 gewoon gemiddelde samples).
Maar het geheugen en CPU gebruik is vele malen lager.

Dat voorbeeld was van Hardbass, niet van mij :)

Maar dat werkt wel een stuk beter dan dit nieuwe voorbeeld.
Hier krijg je alleen maar een fout resultaat doordat een deel van het vorige resultaat bij de nieuwe waarde wordt opgeteld.

blackdog

Golden Member

Hi,

De Arduino IDE werkt weer met de oplossing gevonden op het forum van arduino.cc

Veel tijd verprutst door de domme actie van Arduino Coders...
Typisch gevalletje dat je software afhankelijk is van je Internet verbinding, lijkt wel op een "kill switch" van de Arduino IDE fabrikant. :+
Wat deze fout betreft mogen ze van mij diep door het zand getrokken worden....
(Ze geven zelf al aan, dat ze veel beter moeten gaan testen, sic...)

Temperatuur Sensoren
Verder nog wat uitgezocht over temperatuur sensoren en wat testten gedaan met mijn sensor collectie.
Er is eigenlijk weinig te vinden die hoge resolutie kan leveren en die ook redelijk stabiel zijn of zelfs maar verkrijgbaar voor en redelijke prijs.

Ten opzichte van mijn eerdere zoekopdracht jaren geleden naar sensoren, zijn er maar een paar nieuwe sensoren die gebruikt kunnen worden in mijn toepassing, met de eisen die ik hiervoor stel.

Het hele probleem is natuurlijk dat in de sensoren computers zitten, lage ruis moeten hebben en ook een heel laag stroomverbruik, dit i.v.m. eigen opwarming.
Begrijp mij niet verkeert, ik vind het heel knap wat ik nu kan kopen t.o.v. 10 jaar geleden, er is zoveel vooruitgang op sensoren gebied!
Alleen al deze sensoren van TI: LMT70, TMP61, TMP117 en de HDC2021, en er zijn nog een tiental fabrikanten met moderne sensoren.

Een mooi voorbeeld is de BME280, maar die een flinke opwarming heeft als je hem continu zou uitlezen.(wordt vermeld in da datasheet)
Dit continu uitlezen is in mijn toepassing natuurlijk niet nodig, 1x per 30 seconde zou voldoende zijn, de temperatuur uitlezing van deze sensor is alleen ter controle
om te zien of de andere twee sensoren en de BME280 verlopen t.o.v elkaar, dit is een meet/doe ervaring op oventje. ;)

Maar dit opwarmen van je sensor, welke het ook is , is wel iets waar je rekening mee moet houden.

Middeling code
Leuk dat jullie meerdere vormen van middeling hier laten zien, maar ik gaf al eerder aan, dat mijn code voorlopig klein genoeg is om in een Pro Mini te passen.
Loop ik alsnog vast, dan kom ik terug op jullie alternatieve filtering voorstellen.

I2C rotary encoders
Voor de makkelijkheid heb ik wat rotary encoders via i2c aangeschaft van Sparkfun.
Deze encoders kan je met een vier aderig kabeltje doorlussen en ook softwarematig van een ander adres voorzien.
Alle debounce is al ingebouw en ze hebben een knopje dat aaangestuurd/verlicht wordt door ene drie kleuren LED, daar heb ik verder geen behoefte aan, maar het kan.
Dit alles wordt afgehandeld door een AT-Tiny84 onder op het printje.

Ook de counter limieten kan je instellen in de library voor deze modules, laat het nu zo zijn, dat in twee van deze modules nog de eerste versie firmware zit en de limiten dan nog niet werken...
Deze documentatie is nogal halfbakken wat het updaten van de firmware betreft en via Sparkfun krijg ik geen reactie.
Dus hier bij een link naar de firmware die ik gevonden heb voor dit product en hoor graag jullie bevindingen hoe ik die firmware in de AT-Tiny84 krijg die onder op het printje zit.
Dat zal via de i2c bus moeten, daar er geen andere bus op het printje van de QWIIC TWIST zit.

Link firmware pagina Sparkfun QWIIC TWIST zit.
https://github.com/sparkfun/Qwiic_Twist/tree/master/Firmware/Qwiic_Twi…

Dan vast en gegroet,
Bram

Waarheden zijn "Illusies waarvan men vergeten is dat het illusies zijn"

Programmeren via I2C gaat niet zonder speciale bootloader.

Maar op het schema staat wel een ISP connector (J7).
Die zit ook op de print volgens mij, al is hij wel tamelijk onzichtbaar gemaakt.

blackdog

Golden Member

Hi deKees,

Heel opmerkzaam van je. :-)
Ik heb net bericht gekregen dan ik de twee printjes met de oude firmware mag terug sturen om dan weer twee printjes met de goede firmware te krijgen.

Misschien hebben de printjes die ik hier heb al die speciale bootloader...
Daar heb ik totaal geen kaas van gegeten.

Ik denk nog even na over het terug sturen, kost ook weer geld.
Verder doet de gene met wel de 1.2 versie van de firmware, niet wat wat ik graag wil met de max/min setting, dus tja, met niet echt happy met de aanschaf.

Ik heb net nog een keer de omschrijving in de voorbeeld code van "Example12_SetLimit.ino" gelezen, lezen jullie het ook eens...


This example shows how to set the max encoder value.
For example, setting the limit to 359 will not allow the encoder read values to go above 359, looping back to zero instead.
Useful when the encoder value is mapped directly onto a volume setting, FM freq, etc.

This feature is available on Qwiic Twist firmware v1.2 and above.

Het klopt dat de code niet verder telt dan de hier als voorbeeld opgegeven 359 en daarna doodleuk naar "0" en daarna weer verder omhoog gaat.
Als voorbeeld wordt een volume! setting gegeven of b.v. frequentie instellening aangegeven waarbij dat makkelijk zou zijn.

Ware het niet dat als je naar "0" draaid en er overheen gaat je in één keer naar 359 spring, MAXIMAAL VOLUME!
Geen idee wat die coders roken, maar sporen doen ze niet in mijn ogen.

Er zitten allerlij functies in de library/firmware zoals hoelang geleden je de knop hebt aangeraakt, drukken of draaien enz.
Mooi, prachtig, maar wat betreft basis functies ontbreekt het gewoon.

Ik zou in de code de minimale en de maximale waarde willen aangeven zoals dit: twist.setMinLimit(18); en twist.setMaxLimit(275);
Dit samen met de twist.setCount(33); heb je dan de minimale functies die de moduul in mijn ogen zou moeten hebben.

Mooi zou zijn dat je het dynamisch gedrag ook zou kunnen aanpassen, dus sneller draaien maakt grotere stappen van de counter.
Dit alles wou ik ook aan Sparkfun laten weten of op hun forum te vragen, ware het niet dat beide niet reageren op mijn verzoeken via e-mail of account aanmaak.

Nu zit ik met modules die niet doen wat ik graag wil.
Misschien wil ik wel te veel...

Het doel is dus met drie encoders via i2c de P, de I en de D in te kunnen stellen als de oven is ingebouwd, net als de mogelijkheid een kleine temperatuursprong te doen.
Dit om de PID waarde te testen/instellen en de waarden dan uiteindelijk op te slaan in de processor als ik de goede waarden hiervoor heb gevonden.
De temperatuur sprong kan ik met een drukknoppje doen via de i2c extender daar hoeft in principe geen encoder aan.

Waarom i2c gebuik, dat is om een minimale hoeveelheid bedrading van/naar de oven te laten lopen om het zo stabiel mogelijk te houden.
De controller en de ADC komen in de oven net als de MOSFet die de bifilaire gewikkelde verwarming aanstuurd.

Zie ieder draadje naar/van de oven maar als een gat met een bepaalde diameter in je emmer met water, hoe meer draadjes en ook hoe dikker het draadje,
des te meer moet je de emmer steeds bijvullen om het waterniveau op het streepje in de emmmer te houden.
Met de daarbij behorende "onrust" (thermiek van de lucht in de oven) in het water.

Nu moet ik wat code gaan fabrieken die als je voorbij de limit gaat stel 62 dat ik dan de counter weer terug set met de "setCount" functie
Zoiets van: als count = gelijk of hoger is dan 62 dan setCount(62) en het zelfde voor de laagste waarde die ik wil hebben, kijken of ik daar vanavond aan kan werken.

Dat waren weer even de perikelen van gisteren en vandaag betrteffende de oven sturing.

Groet,
Bram

Waarheden zijn "Illusies waarvan men vergeten is dat het illusies zijn"

Ik weet niet of het helpt, maar ik heb juist vorige week een paar printjes binnengekregen met 3 encoders en een I2C interface. Ik heb nog wel wat printjes beschikbaar.

Basis software is beschikbaar, inclusief versnelling, maar zonder limieten. Die kun je volgens mij net zo goed aan de host kant inbouwen. Ik ga nog wel een .ino driver maken die dat ondersteunt.

Er zitten wel erg veel lichtjes op. Dat is vooral voor het edukatieve effect. In de praktijk kun je die wel weglaten.

Ware het niet dat als je naar "0" draaid en er overheen gaat je in één keer naar 359 spring, MAXIMAAL VOLUME!

Het kan bij sommige toepassingen handig zijn het is natuurlijk niet alleen voor volume alhoewel ik nu even niets kan bedenken. Ik zou toch liever hebben dat hij gewoon op 0 blijft hangen hoelang je ook draait. Ook voor de max waarde die dan ineens naar 0 springen is ook niet altijd wenselijk. En ik zou ook liever hebben dat het op die waarde blijft hangen hoe ver je ook draait.

Ik ben wel blij me je nieuwe vondst het maakt het gebruik van encoders een stuk eenvoudiger

Ik snap heel goed dat je de smooth lib blijft gebruiken. Het werkt en je snapt hoe het werkt. Het kan beter maar is absoluut niet noodzakelijk. Daarbij komt dat ik mijn voorbeeldje een C++ class is, dat is die library ook maar dat zit grotendeels onderwater verstopt.

Wat betreft het regelen van de PID, als ik het goed begrijp doe je dit eenmalig en programmeer je het vervolgens hard coded in je controller? Ik zou zelf niet de moeite nemen om dit met encoders te doen. Ik zou zelf via de seriële interface een paar commando's beschikbaar maken om de PID waardes aan te passen. En meteen een commando om de samples naar buiten te gooien zodat je ze op de PC in een grafiek kan plotten. Dan kan het feest pas echt beginnen, je kunt de PID namelijk berekenen. Een oud docent van mij heeft een mooi stukje hierover op zijn website staan: http://www.vandelogt.nl/uk_regelen_pid.php

Eigenlijk wel leuk om zoiets te bouwen, ik zoek al een tijdje naar een 'oventje' wat rond de 300°C kan blijven hangen. Nu is voor mij de nauwkeurigheid van een gasbrander al voldoende maar des al niet te min leuk om te bouwen. Als ik nog eens wat tijd over heb zal ik eens kijken of ik dat in een Arduino kan proppen.

blackdog

Golden Member

Hi deKees,

Altijd leuk om met je print te stoeien, stuur me een e-mail dan kunnen we de verkoop regelen.
Waarvoor heb je de processor bedoeld op het printje, algemeen?

hardbass
Dat ik niet direct met je code aan het werk ga is gewoon tijd die ik nodig heb om code te doorgronden...
Net voor ik dit stukje type, heb ik weer je stukje code bestudeerd, ik raak door mijn taalprobleem in de war door b.v. "weight" op twee plekken en de de vele versies van "avg"
Als je dan met Avg en avg aankomt moet ik tien keer kijken wat er nu bedoeld wordt.

Je begrijpt denk ik wel dat ik dan liever de tijd gebruik aan de code die nu al goed genoeg werkt en aan de rest van het project.

Ik heb zoiets waar ik nu mee bezig in dit topic al eens meer gemaakt, andere sensoren, ander oven materiaal en veel aanpassingen aan de PID waarden gedaan om te testen wat de effecten waren, empirisch leren.
Je wordt gek van het uploaden, dan draai ik liever aan een paar encoders voor de PID waarden en dan samen met een schakelaar waarmee ik de temperatuur een klein sprongetje kan laten maken.
Dit om de effecten van de verandering vvan de PID waarden te testen.

Met de andere PID oven hoefte ik door de extreem goede koppeling tussen de sensor en de ovenbuis (18B20 in een dikke Alu buis wand geboord en gelijmt) maar weinig in te stellen,
maar dat wist ik niet toen ik begon. ;)

De vorige ovenhad weinig PID nodig, dit waren de settings voor die oven, die trouwens binnen een paar honderste °C bleef.

c code:


const byte p = 40;
const byte i = 1;
const byte d = 1;
int WindowSize = 1000;
double Setpoint, Input, Output;

De website die je aangaf had ik al eens gezien, maar wat voor jouw stukje code geld betreffende mijn brein, geld ook voor die website,
kost zeer veel moeite voor mij om er een nagel achter te krijgen.

Zie de i2c manier die ik nu kies ook maar voor de toekomst zodat ik een soort testkastje kan maken met een aantal i2c devices zodat ik snel zaken kan testen/ontwikkelen.
Daarom lijkt mij het printje van deKees ook handig.

Oja, ik heb er ook nog aan gedacht om de tweede TMP37 sensor die op de Referentie print zit, te gebruiken als meetsensor voor de PID.
Je zou dat een beetje kunnen vergelijken met het brouwen van bier door de langere tijdconstante die hierbij optreed.
Veder heb je dan ondermeer als nadeel dat de ADC op de controlerprint minder stabiel gehouden wordt.
Maar ik blijf voorlopig bij mijn eerste opset met de TMP37 Sensor die aan de ovenbuis vast zit.
Zoveel afwegingen...

Groet,
Bram

Waarheden zijn "Illusies waarvan men vergeten is dat het illusies zijn"

Als je er baat bij hebt kan ik de code wel wat lees vriendelijker neerzetten. Ik kan me voorstellen dat het verwarrend is om te lezen met de benamingen die ik gekozen heb en geen commentaar bij de code. Je zou mijn antwoord kunnen vergelijken met een stukje schema zonder uitleg. :)

Het blijft lastig te snappen als je het concept 'object oriented programming (OOP)' niet kent. Hier is wel weer veel over te vinden mocht je dat interessant vinden. Wat trouwens heel goed werkt om te leren begrijpen hoe software werkt is debugging. Stap voor stap door de code gaan heeft mij erg veel geleerd!

c code:




//Definieer het object Average
class Average
{
	//Om het gemiddelde te kunnen uitrekenen moeten een aantal waardes worden onthouden.
	//Deze staan binnen de scope van dit object. (aangegeven met brackets '{}') 
	//Deze variabelen zijn dus enkel te benaderen binnen dit object.
	
	//Hoe zwaar nieuwe samples meetellen in de berekening.
    int internal_weight = 0;
	
	//Een variabele om het resultaat in op te slaan, deze hebben we bij iedere sample weer nodig.
    float internal_result = 0;
    
public:
	
	//De constructor van het object Average. Deze wordt 1x aangeroepen bij het creeeren van dit object. (Dit gebeurt in de main())
    Average(int weight)
    {
        internal_weight = weight;
    }
    
	//De functie die voor iedere nieuwe sample opnieuw wordt aangeroepen om het nieuwe gemiddelde te berekenen.
    float Do(float input)
    {
		//Het rekensommetje om het nieuwe gemiddelde te berekenen.
		internal_result = internal_result + (input - internal_result) / internal_weight;

		//Geef het resultaat terug.
        return internal_result;
    }
    
};




int main()
{
	//Ik maak hier 3 instances van het object 'Average'. Zo kunnen er 3 gemiddeldes worden berekend.
	//Je ziet dat hier de constructor van het object 'Average' wordt aangeroepen met een argument van 3.
    Average avgCalculator1 = Average(3);
	Average avgCalculator2 = Average(3);
	Average avgCalculator3 = Average(3);
    
    //Een klein testje, bereken het gemiddelde 20x
    for(int i = 0; i<20; i++)
    {
		//Dit zouden de meetwaardes moeten worden, nu is hier statisch een waarde ingevuld voor het testen.
		float measuredValue1 = 1;
		float measuredValue2 = 8;
		float measuredValue3 = 4;
		
		//Bereken een nieuw gemiddelde.
		float averageValue1 = avgCalculator1.Do(measuredValue1);
		float averageValue2 = avgCalculator2.Do(measuredValue2);
		float averageValue3 = avgCalculator3.Do(measuredValue3);
		
		//Print de nieuwe waardes.
        printf("%f \t", averageValue1);
		printf("%f \t", averageValue2);
		printf("%f \n", averageValue3);
    }
}

blackdog

Golden Member

Hi hardbass, :-)

Dank je voor je inzet, ik lees je code morgen als ik wat frisser ben.
Dan beloof ik dat ik echt mijn best doe met wat opmerkingen over vragen die bij me opkomen.

Ik zij in een vorige post dat ik de limiten zou testen vanavond en dat heb ik gedaan, zal jullie ook vertellen waar de meeste tijd in zat.
Ik worstel echt met wanner nu welke haakjes komen en hoeveel van welke
Waarom moet twist.getCount() tussen extra haakjes () staan in onderstaande vergelijking?

c code:


  if ((twist.getCount()) >= 15) {

Nog een puntje waarom het in eerste instantie niet werkte, als je deze functie gebruikt om de Maximale waarde van de counter op te geven: twist.setLimit(15);
Dan werken de ingestelde limiten niet goed, als je de twist.setLimit echter op "0" set werke het zonder storingen,zo dus twist.setLimit(0);
Dan zet de library deze functie uit.

De code die nu netjes met limiten werkt staat hieronder en deze geeft een melding als de max of min waarde bereik is, kan handig zijn.
Bij mij gebruikt om de code te testen in de serieel monitor.

c code:


#include "SparkFun_Qwiic_Twist_Arduino_Library.h"                       //Click here to get the library: http://librarymanager/All#SparkFun_Twist
TWIST twist;                                                            //Create instance of this object

void setup() {
  Wire.setClock(400000);                                                //Als het goed is werkt de i2c bus onderdelen die ik gebruik allen op deze snelheid 

  Serial.begin(115200);                                                 //Set de serieele monitor op een hoge snelheid om beter foutjes te kunnen dedecteren
 
  twist.begin();

  twist.setLimit(0);                                                   // setLimit moet op "0" staan voor goede werking van de limit waarden in de loop code

  twist.setCount(8);                                                   // plaatst een voorkeurwaarde in de counter na het resetten van de controler, hier is dat de waarde 8
  
}

void loop() {
  
  if ((twist.getCount()) >= 15) {
  twist.setCount(15);
  Serial.println();
  Serial.print("Counter Max. is bereikt!");
  }
  
  else if ((twist.getCount()) < 0) {
  twist.setCount(1);
  Serial.print("Counter Min. is bereikt!");
  }
  
  Serial.print("Count: ");
  Serial.print(twist.getCount());
  Serial.println();


Blij dat dit werkt, dan hoef ik de twee printjes die oude firmware hebben niet terug te sturen.

Groet,
Bram

Waarheden zijn "Illusies waarvan men vergeten is dat het illusies zijn"
blackdog

Golden Member

Hi

Nog even snel voor ik naar bed ga...

Ik wil een dubbele vergelijking doen, als de teller niet nul is maar ook niet de waarde 15 heeft dan moet de LED onder de encoderknop groen worden.
Verschillende voorbeelden geprobeerd maar kan iemand mij even in de goede richting schoppen?
En nog belangrijker vertellen wat ik verkeerd doe.

Stukje van de code die ik niet goed krijg.

c code:


void loop() {
  
  if ((twist.getCount()) >= 15) {
  twist.setCount(15);
  twist.setColor(255, 0, 0);                                     // Maakt de LED rood

  Serial.println();
  Serial.print("Counter Max. is bereikt!");
  }
  
  else if ((twist.getCount()) < 0) {
  twist.setCount(0);

  twist.setColor(0, 0, 255);                                     // Maakt de LED blauw
  Serial.print("Counter Min. is bereikt!");
  }
 
 
  Serial.print("Count: ");
  Serial.print(twist.getCount());
  Serial.println();

 if ((twist.getCount()) > 0) && ((twist.getCount()) < 15){     // het gaat om deze twee regels, Deze regel bevat fouten! als de counterwaarde niet 0 is en ook niet 15 is, dan moet de LED in de encoder groen worden
  twist.setColor(0, 255, 0);                                   // het gaat om deze twee regels, deze regel maakt de LED in de encoder groen en dat commando is in principe goed
 }



  delay(1);
}

Dank en groet,
Bram

Waarheden zijn "Illusies waarvan men vergeten is dat het illusies zijn"

Als de led niet rood of blauw brandt, dan moet hij groen branden.
Dus dit zou moeten werken:

c code:


void loop() {
  
  if ((twist.getCount()) >= 15) {
  twist.setCount(15);
  twist.setColor(255, 0, 0);                                     // Maakt de LED rood

  Serial.println();
  Serial.print("Counter Max. is bereikt!");
  }
  
  else if ((twist.getCount()) < 0) {
  twist.setCount(0);

  twist.setColor(0, 0, 255);                                     // Maakt de LED blauw
  Serial.print("Counter Min. is bereikt!");
  } 

  else {
  twist.setColor(0, 255, 0);                                   // Maak led groen als de led niet rood of blauw brandt
  }
 
 
  Serial.print("Count: ");
  Serial.print(twist.getCount());
  Serial.println();
 }



  delay(1);
}

Je gaat mis met je haakjes. Je schrijft:

c code:


 if ((twist.getCount()) > 0) && ((twist.getCount()) < 15){     // het gaat  

maar moet zijn:

c code:

 
if (((twist.getCount()) > 0) && ((twist.getCount()) < 15)){     // het gaat
Bezoek mijn neefjes' site: www.tinuselectronics.nl
blackdog

Golden Member

Hi ohm pi, :-)

Dat klopt, je voorbeeld werkt.
Ik zie nu ook dat als je meerdere vergelijkingen doet, de hele vergelijking ook nog eens tussen haakjes moet staan zoals jij ook aangeeft.

Maaaaaar....
Ik heb een vreemd effect, als eerste wat goed gaat.
Als ik omhoog draai en bij 15 aankom wat ik als maximum heb gesteld, dan wordt de counterwaarde net jes begrenst en ook de LED i nd encoder wordt rood.
Draai ik nu 1 klik linksom, dan wordt de counter waarde netjes 14 en de LED wordt groen.

En dan nu wat niet goed gaat.
Draai ik vanaf 14 verder omlaag naar counter stand "0" (stat op "0" in de serieel monitor) dan blijft de LED nog steeds groen!
Draai ik nu nog 1 klik linksom dan blijft de counter op "0" staan en nu wordt blauw.
Draai ik de encoder 1 klik weer rechtsom dan wordt direct de LED weer groen bij de couter waarde van "1"

Draai ik nu weer linksom dan zijn er weer twee klikjes nodig om de LED blauw te krijgen, hoe kan dit?
Het lijkt er op dat de eerste vergelijking of de counter waarde groter dan "0" is niet werkt...
Weer een setje haakjes vergeten? |:(

De code

c code:


#include "SparkFun_Qwiic_Twist_Arduino_Library.h"                       //Click here to get the library: http://librarymanager/All#SparkFun_Twist
//#include <EEPROM.h>
//int addr = 0;

TWIST twist;                                                            //Create instance of this object

void setup() {
  Serial.begin(115200);
  Serial.println("Qwiic Twist Counter Limit voorbeeld");

  twist.begin();

  Wire.setClock(400000);                                               //Optional: After Twist begin(), increase I2C speed to max, 400kHz

  twist.setLimit(0);                                                   // setLimit moet op "0" staan voor goede werking van de limit waarden in de loop code

  twist.setCount(8);                                                   // plaatst een voorkeurwaarde in de counter als er opgestart wordt b.v. hier 8
  
}

void loop() {
    
  if ((twist.getCount()) >= 15) {
  twist.setCount(15);                                                 // als de counter een waarde heeft die hoger is dan 15 zet de counter terug naar 15 
  twist.setColor(255, 0, 0);                                          // als bovenstaande waar is, maak dan de encoder LED rood

  Serial.println();
  Serial.print("Counter Max. is bereikt!");
  }
  
  else if ((twist.getCount()) < 0) {
  twist.setCount(0);                                                  // als de counter een waarde heeft die lager is dan "0" zet de counter terug naar "0"
  twist.setColor(0, 0, 255);                                          // als bovenstaande waar is, maak dan de encoder LED blauw
  Serial.print("Counter Min. is bereikt!");
  }
 
 
  Serial.print("Count: ");
  Serial.print(twist.getCount());
  Serial.println();

 if (((twist.getCount()) > 0) && ((twist.getCount()) < 15)){          // als de counter waarde groter is dan "0" en lager is dan "15" maak dan de encoder LED groen  
  twist.setColor(0, 255, 0);                                          // als bovenstaande waar is, maak de encoder LED groen
 }

  delay(1);
}

Groet,
Bram

Waarheden zijn "Illusies waarvan men vergeten is dat het illusies zijn"

Bij de 'nul' gaat het niet goed. Bij de 'vijftien' gaat het wel goed.
Er is een verschil hoe je 'vijftien' behandelt en hoe je de 'nul' behandelt.
Bij 'vijftien' schrijf je:

c code:

  if ((twist.getCount()) >= 15) {
  twist.setCount(15);                                                 // als de counter een waarde heeft die hoger is dan 15 zet de counter terug naar 15 
  twist.setColor(255, 0, 0);                                          // als bovenstaande waar is, maak dan de encoder LED rood
enz.

Bij 'nul' schrijf je:

c code:

  else if ((twist.getCount()) < 0) {
  twist.setCount(0);                                                  // als de counter een waarde heeft die lager is dan "0" zet de counter terug naar "0"
  twist.setColor(0, 0, 255);                                          // als bovenstaande waar is, maak dan de encoder LED blauw
enz.

Volgens mij ben je er als je daar ook schrijft:

c code:

  else if ((twist.getCount()) <= 0) {
  twist.setCount(0);                                                  // als de counter een waarde heeft die lager is dan "0" zet de counter terug naar "0"
  twist.setColor(0, 0, 255);                                          // als bovenstaande waar is, maak dan de encoder LED blauw
enz.

Heb je geen last in standje 15 dat hij telkens schrijft: "Counter Max. is bereikt!"?

Bezoek mijn neefjes' site: www.tinuselectronics.nl
blackdog

Golden Member

Hi ohm pi

Ik had expres "< 0" gebruikt i.p.v "<= 0" omdat ik met de laatste vergelijking, dus gelijk of kleiner dan "0" als ik snel draai,
waarden krijg die kleiner zijn dan "0" in de serieele monitor, die dan wel weer worden gecorrigeerd naar de counter waarde "0".
Ik bedoel natuurlijk -1, -2, -3 enz. afhankelijk van hoe snel ik draai.

Ik begrijp echt niet waarom er een verschil is in het gedrag.

Groet,
Bram

Waarheden zijn "Illusies waarvan men vergeten is dat het illusies zijn"

Ik heb een vreemd effect, als eerste wat goed gaat.
Als ik omhoog draai en bij 15 aankom wat ik als maximum heb gesteld, dan wordt de counterwaarde net jes begrenst en ook de LED i nd encoder wordt rood.
Draai ik nu 1 klik linksom, dan wordt de counter waarde netjes 14 en de LED wordt groen.

En dan nu wat niet goed gaat.
Draai ik vanaf 14 verder omlaag naar counter stand "0" (stat op "0" in de serieel monitor) dan blijft de LED nog steeds groen!
Draai ik nu nog 1 klik linksom dan blijft de counter op "0" staan en nu wordt blauw.
Draai ik de encoder 1 klik weer rechtsom dan wordt direct de LED weer groen bij de couter waarde van "1"

Als ik dit lees komt dat overeen met wat er in je code staat. Er gebeurt dus niets vreemds. Ow en besteed ook tijd aan de opmaak van je code, dit maakt het een stuk leesbaarder. Nu zag ik dat mijn opmaak in het vorige voorbeeldje ook niet meer klopte ik vermoed dat CO er iets mee heeft gedaan.

Wat heb ik gedaan:
stap 1, Doe de limitering.
stap 2, Aansturen ledjes.
stap 3, Print de actuele tel waarde.

Wat trouwens ook kan helpen is om eerst een flow voor jezelf uit te tekenen. Dat geeft vaak de fouten weer. Ook een handige tip, lees de code regel voor regel zoals de processor dat zou doen.

Als ik goed begrijp wat je wilt zou ik er het volgende van maken.

c code:



void loop() 
{
	//Limiet bovengrens
	if (twist.getCount() > 15) 
	{
		twist.setCount(15);                                                 
		Serial.println("Counter max berijk, gecorrigeerd naar 15.");
	}
	
	//Limiet ondergrens
	if (twist.getCount() < 0) 
	{
		twist.setCount(0);                                                 
		Serial.println("Counter min berijk, gecorrigeerd naar 0.");
	}
	
	
	if(twist.getCount() == 0)
	{
		twist.setColor(255, 0, 0); 
	}
	else if(twist.getCount() == 15)
	{
		twist.setColor(0, 0, 255); 
	}
	else
	{
		twist.setColor(0, 255, 0); 
	}
	  
	Serial.print("Count: ");
	Serial.println(twist.getCount());

	delay(1);
}

Die extra haakjes zijn niet echt nodig, maar mag wel:

code:


 if ((twist.getCount()) >= 15) {

is hetzelfde als

code:


 if ( twist.getCount()  >= 15) {

Ook als het ingewikkelder wordt zijn de haakjes niet echt nodig.

code:


 if (((twist.getCount()) > 0) && ((twist.getCount()) < 15)){

Kun je ook schrijven als

code:


 if (( twist.getCount() > 0) && ( twist.getCount() < 15) ) {

of zelfs als

code:


 if ( twist.getCount() > 0 && twist.getCount() < 15 ) {

Maar die laatste is gevaarlijk want dan gaat de compiler zelf de volgorde van de bewerkingen bepalen. Dat zal in dit geval nog wel goed gaan ook, maar voor mij wordt het dan wel moeilijk om het nog te volgen. Ik zou dus hier voor optie 2 gaan.

De Arduino IDE helpt wel bij het plaatsen van haakjes. Als de cursor naast een haakje staat dan komt er een vierkantje bij het corresponderende haakje aan de andere kant. Dan kun je zien of er staat wat je bedoelt.

Dat werkt ook met krulhaakjes en met rechte haakjes, en ook als je een pagina verder scrolt om de andere kant in beeld te krijgen.

Op 12 juni 2020 16:07:42 schreef deKees:

code:


 if ( twist.getCount() > 0 && twist.getCount() < 15 ) {

Maar die laatste is gevaarlijk want dan gaat de compiler zelf de volgorde van de bewerkingen bepalen.

Als die compiler zelf iets verzint, dan moet je die zo snel mogelijk weggooien. De evaluatievolgorde is ook in de laatste voorbeeld precies vastgelegd en een goede compiler wijkt daar dus niet van af. Voor de ene programmeur ziet het er overzichtelijk uit, want er zijn weinig haakjes. Een ander denkt er anders over en die voegt extra haakjes toe om het voor hem of haar overzichtelijk te maken. Een probleem is wel dat je aan de instructie "twist.getCount()" niet kunt zien of het een functie of een macro is. Bij een macro zijn extra haakjes een goede voorzorgsmaatregel om de code correct te evalueren.

Op 12 juni 2020 13:22:37 schreef blackdog:
Hi ohm pi

Ik had expres "< 0" gebruikt i.p.v "<= 0" omdat ik met de laatste vergelijking, dus gelijk of kleiner dan "0" als ik snel draai,
waarden krijg die kleiner zijn dan "0" in de serieele monitor, die dan wel weer worden gecorrigeerd naar de counter waarde "0".
Ik bedoel natuurlijk -1, -2, -3 enz. afhankelijk van hoe snel ik draai.

Ik begrijp echt niet waarom er een verschil is in het gedrag.

Groet,
Bram

In je originele code gebeurt het volgende:
We gaan vanuit dat de teller van 14 naar 0 gaat.
Als de teller '1' is dan brandt de groene led.
De instructie

c code:

else if ((twist.getCount() < 0) {
  twist.setCount(0);                                                  // als de counter een waarde heeft die lager is dan "0" zet de counter terug naar "0"
  twist.setColor(0, 0, 255);                                          // als bovenstaande waar is, maak dan de encoder LED blauw
enz.

wordt niet uitgevoerd. De blauwe led wordt niet aangezet en de groene led wordt niet uitgezet
Nu maak je de teller '0'
De code

c code:

 if (((twist.getCount()) > 0) && ((twist.getCount()) < 15)){ 

zet alleen maar de groene led aan en overige kleuren uit. Deze code wordt niet meer uitgevoerd.
De blauwe led gaat niet aan en de groene led gaat niet uit, want twist.getCount() is '0'. De code

c code:

else if ((twist.getCount() < 0) {
  twist.setCount(0);                                                  // als de counter een waarde heeft die lager is dan "0" zet de counter terug naar "0"
  twist.setColor(0, 0, 255);                                          // als bovenstaande waar is, maak dan de encoder LED blauw
enz.

wordt niet uitgevoerd.
Als je nog een klikje omlaag draait, dan wordt twist.getCount() -1.
Nu wordt de code

c code:

else if ((twist.getCount() < 0) {
  twist.setCount(0);                                                  // als de counter een waarde heeft die lager is dan "0" zet de counter terug naar "0"
  twist.setColor(0, 0, 255);                                          // als bovenstaande waar is, maak dan de encoder LED blauw
enz.

wel uitgevoerd. De blauwe led gaat nu aan en "twist.setCount(0)" wordt terug op nul gezet.
Draai je weer naar "1", dan wordt de code

c code:

 if (((twist.getCount()) > 0) && ((twist.getCount()) < 15)){          // als de counter waarde groter is dan "0" en lager is dan "15" maak dan de encoder LED groen  
  twist.setColor(0, 255, 0);                                          // als bovenstaande waar is, maak de encoder LED groen
 }

uitgevoerd en de led verspringt van blauw naar groen.

De manier waarop hardbass de code schrijft is een stuk overzichtelijker dan wat wij schrijven. Enig minpuntje is dat hij printinstructies in zijn begrenzingscode opneemt. Deze printopdrachten wijken iets af van wat jij geschreven hebt. Ook de plaats wijkt af van zijn eigen programmeervoorschriften.

stap 1, Doe de limitering.
stap 2, Aansturen ledjes.
stap 3, Print de actuele tel waarde.

[Bericht gewijzigd door ohm pi op 12 juni 2020 20:59:28 (64%)]

Bezoek mijn neefjes' site: www.tinuselectronics.nl
blackdog

Golden Member

Hi,

Morgen verder met het project, maar vandaag twee printjes van deKees binnen gekregen, en daar heb ik er één van bijna volgebouwd.
Dank Kees!

Ik ben één printje aan het opbouwen, en dit is voor mij de achterzijde en voorzien van aansluitstripjes.
https://www.bramcam.nl/Diversen/Rotary3-deKees/Rotary3-deKees-01.png

De voorzijde, zie je het deKees???
De LED's zijn nog niet aangebracht, moet ze nog uitzoeken, en de hoogte uitmeten.
https://www.bramcam.nl/Diversen/Rotary3-deKees/Rotary3-deKees-02.png

Het IC op het voetje is wel een beetje hoog, maar ik heb het uitgemeten, met een extra moer en tandring op de encoders, komt de moer aan de voorzijde net mooi vlak uit.
Ik bouw een klein kastje met de drie encoders er in, i2c display, i2c klok module in misschien en mischien nog een paar onderdelen die handig zijn voort een breadboard opset.
Ik weet niet of deKees zelf nog een een topic maakt, maar ik wou in ieder geval mijn i2c breadboard hier op CO laten zien.

DeKees,
Ik doe via de e-mail wel mijn opmerkingen, maar spaar even wat op, tot dat ik het eerste printje getest heb.

Groet,
Bram

Waarheden zijn "Illusies waarvan men vergeten is dat het illusies zijn"

Hey,

Is het nog gelukt met de regeling?

Ik kon het zelf niet laten om ook een beetje met PID te spelen. Ik heb de regelaar van die link een paar posts geleden geïmplementeerd in de Arduino. Om te testen heb ik een weerstand aan een DS18B20 getaped. Ik heb ervoor gekozen om in de test niets te filteren, de DS18B20 geeft vrij nette sample waardes dus dat is in mijn situatie niet nodig. De Arduino gooit de gemeten waarde en de PWM duty cycle naar buiten die ik dan plot in een grafiekje. De temperatuur is aangegeven met de rode lijn in 10°C/div en een offset van -20°C. De gele lijn geeft de duty cycle weer van 0 - 255. (64/div en een offset van -255)

De setpoint waar hij naartoe regelt is 40°C . Zoals je ziet heeft hij behoorlijk overshoot tot wel 50°C en hij is ook niet helemaal stabiel op het einde. Hij oscilleert nog wel iets, maar dat is natuurlijk een kwestie van tunen. In theorie zou ik met deze data een schatting kunnen maken van de overdracht van het systeem. Als ik die heb zou ik de optimale PID kunnen berekenen. Maar daar moet ik wel weer even de theorie voor boven halen. Misschien wel een leuke uitdaging

De instellingen van de PID:
Ts = 1 sec
P = 100
I = 10
D = 0

blackdog

Golden Member

Hi hardbass, :-)

Leuk dat je er mee bezig bent!
ik ben zelf nu weer even bezig met de stroomtransformator stuurprint en een temperatuur sensor calibrator die ik nog af moest maken.
Dat ding heb ik nu al regelmatig nodig gehad maar had nog wat mechanisch werk nodig om hem af te bouwen, dat is nu gestart.

Uhm, ik heb hier op CO al een topic over een PID oven en die kan je vinden in de onderstaande link

Scrol dan naar deze tijd, da nkan je zien wat mogelijk is met een Nano die opgevoerd is, dat is andere externe referentie en goed ontkoppeld.
Gepost zondag 13 november 2016 11:40:37

https://www.circuitsonline.net/forum/view/133966/5#highlight=pid

Nu weer verder met de relais sturing van de stroommeet trafo!

Groet,
Bram

Waarheden zijn "Illusies waarvan men vergeten is dat het illusies zijn"