Sida 1 av 3
Ställa in tal display med knappar och jämföra detta med Rx
Postat: 30 juni 2017, 23:46:57
av Henry
Jag har nedan kod som funkar som jag vill genom att den skriver ut det specifika värdet från en vakuumsensor på en display och kommer ingen info så blir man varnad om det då alla funktioner kommer att baseras på detta värde.
Funkar fint om än kanske inte efter konstens regler som att tex displayens tecken blinkar lite grand (om man inte tittar rakt på den utan från sidan) i takt med uppdateringsfrekvensen som datan skickas med till sensorn då ju allt går i samma loop, men men och jag är mer än nybörjare i detta så det får gå as is as now.
Det jag hade velat ha implementerat så enkelt som möjligt är att kunna ställa in vakuumnivån genom displayen med knappar så när rätt nivå nås eller lägre av inställt värde så går en utgång hög tills nivån går över satt värde igen då den går låg.
Så tex första siffran ställs in med en upp och en ned knapp, stega vidare till nästa siffra med en knapp och göra samma tills alla är klara och då trycka på en annan knapp som både startar en vakuumpump och öppnar en ventil. Pumpen går då tills rätt nivå eller lägre nåtts vilket stänger ventilen till pumpen vilket då håller vakuumnivån tills det stiger över satt värde igen då ventilen öppnas, osv.
Har ingen aning hur detta kan göras, några tips/hänvisningar åt rätt håll till grejer jag skall titta på för att få ihop något sådant? Då har jag något att gå efter och kanske få ihop något med och kolla upp mer för jag hittar dock inga konkreta exempel på något liknande på nätet som det är nu.
Sensorn ger även ut en linjär analog utgång men då blir det en massa jobb med att anpassa värdet exakt till ADCn och det blir ändå inte exakt vilket jag behöver och spannet är dessutom även på tok för stort för mätaren jag använder, men med en enskild grovvakuummätare så hade det kanske funkat, men då blir det ev en annan tråd.
Gick bara att få ihop nedan kod efter en hel del hjälp härifrån och genomkoll av exempel på nätet om olika grejer, jag är som ni nog alla vet mer än nybörjare på detta så helst gärna ev info därefter.
Kod: Markera allt
#include <LiquidCrystal.h>
LiquidCrystal lcd(40, 42, 28, 26, 24, 22);
String value;
void setup() {
Serial.begin(9600);
Serial.setTimeout(75); //Hade ingen aning om detta innan vilket skapade en jäkla massa huvudbry
pinMode(13, OUTPUT);
lcd.begin(20, 4);
lcd.clear();
delay(1000); //Så att sensorer och allt hinner stabilisera sig
}
void loop() {
delay(200);
Serial.print("@254PR3?;FF"); //Skicka förfråga till sensorn om vakuumnivå 5 ggr i sekunden (klarar 10 ggr men tyvärr inte displayen)
//och få tillbaka tex @254ACK6.48E-7;FF där siffrorna i mitten är värdet
if (Serial.available()) { //Finns det någon data i den seriella bufferten?
digitalWrite(13, LOW); //Om ja gå vidare
lcd.clear();
lcd.print("Vacuum: ");
lcd.setCursor(16, 0);
lcd.print("Torr");
lcd.setCursor(8, 0);
value = Serial.readString();
for (int mod = 7; mod < 14; mod++) { //Skriver enbart ut värdet tex 6.48E-7 på displayen
lcd.write(value[mod]);
}
}
Re: Ställa in tal display med knappar och jämföra detta med
Postat: 1 juli 2017, 10:39:29
av Icecap
Blinkandet tas bort vid att ta bort display.clear() men samtidig se till att det blir fyllt upp i displayen vid att formatera en utskriftsträng ordentligt.
Ögat + display hinner inte med mer än 3 gg/sek, detta kan enkelt lösas med en prescale.
Det är enkelt att dels ta bort det förhatliga delay() och dels att få en snabbare funktion på d3t hela utan att displayen flipprar.
En "meny" för att ställa in värdet är enkelt också - men alla saker kräver att du sluter använda delay() helt.
En timing behövs men i arduino-skiten finns det väl en systemtimer att använda?
Då kan main-loop köra full patte medan displayen uppdateras i sin takt, sensorn läsas i sin takt och knappsatsen läsas i full speed.
Du måste ju även tolka värdet som sensorn skickar så att du kan jämföra värden.
Re: Ställa in tal display med knappar och jämföra detta med
Postat: 1 juli 2017, 11:04:07
av hawkan
Ja det finns massa olika sätt att köra fristående "tasks" i arduino-skiten.
Frågan är vilken nivå och abstractionsnivå man vill ha.
TimerOne är en enkel men den kan bara köra en återkommande rutin.
Freertos är fullständig med multi-tasking med tasks, semaforer, mm.
TaskScheduler är nåt mittemellan.
https://github.com/arkhipenko/TaskScheduler
Den kör jag med nu, verkar smidigt.
Skamlös copy-paste från github
Kod: Markera allt
#include <TaskScheduler.h>
// Callback methods prototypes
void t1Callback();
void t2Callback();
void t3Callback();
//Tasks
Task t4();
Task t1(2000, 10, &t1Callback);
Task t2(3000, TASK_FOREVER, &t2Callback);
Task t3(5000, TASK_FOREVER, &t3Callback);
Scheduler runner;
.. arduino-skit saker ...
void loop () {
runner.execute();
}
Och då gör den det som är i txCallback med de intervall som specats.
Detta är inte preemptive, dvs den ena tasken avbryter inte en annan
utan det sker den ena efter den andra.
Kanske kan vara något.
Re: Ställa in tal display med knappar och jämföra detta med
Postat: 1 juli 2017, 13:29:01
av Icecap
Och man kan köra utan all RTOS o skit också!
Har man bara en systemtimer med en räknare som kan räkna den längsta tiden som behövs är det enkelt.
Jag brukar ha en timer-interrupt som - om de är icke-noll - räknar ner de timer-variabler jag behöver.
Man ger sedan variabeln ett värde som motsvarer den tiden man behöver. Detta brukar jag göra i den snudd som kollar om tiden har gått ut:
Kod: Markera allt
if (!Timeout_1)
{
Timeout_1 = MILISEC(300); // För display-uppdatering
}
MILISEC() är ett macro som ger rätt antal steg för en given tid. Kan såklart ersättas av fasta tal.
Man kan ha ett antal av dessa funktioner i main-loop, i detta fall behövs det en timer till displayen, en timer till att hämta data från sensorn, en timer för läsning av knappar samt en timer för timeout av insignalen.
Med en smart rutin för att ta emot seriella data kan man enkelt fånga texten som kommer i svaret från sensorn och trigga en läsning som omvandlas till ett värde som då kan jämföras med det inlagda värdet.
Alla funktioner finns alltså, det fattas bara ett bra program.
Re: Ställa in tal display med knappar och jämföra detta med
Postat: 1 juli 2017, 14:28:43
av lillahuset
Jag återkommer med min trotjänare sedan tio år.
I mitt fall hanteras systemtiden "ticks" av en 32 bits räknare, det är därför jag använder uint32_t. Har du en 16 bits räknare så använder du en uint16_t.
Räknarens värde läses med getTicks().
Funktionen måste anropas minst så ofta som man får ett overflow i räknaren.
Funktionen garanterar, om du anropar tillräckligt ofta, bara att det är minst "ticks" mellan timeouter, inte högst.
Du kan hantera godtyckligt antal "timers" eftersom du anropar timeout() med en pekare till "timern".
Jag vet att funktionen funkar med räknare som räknar upp men har ingen aning om den funkar med räknare som räknar ner. Det intresserar mig inte.
Kod: Markera allt
/**
* @brief check if *timer has timed out
* @brief initialise *timer by a call with ticks = 0
* @param timer: pointer to timer variable
* @param ticks: number of ticks to wait
* @retval return 0 if not timeout, !0 if timeout
* @date 2012-12-14
*/
int timeout(uint32_t *timer, uint32_t ticks)
{
uint32_t t, diff;
int tout;
tout = 0;
t = getTicks();
diff = t - *timer;
if (0 == ticks || diff >= ticks) {
*timer = t;
tout = 1;
}
Re: Ställa in tal display med knappar och jämföra detta med
Postat: 1 juli 2017, 14:31:40
av hawkan
Så här kan det se ut om man använder TaskScheduler.
Detta följer aurdions sanna anda att man försöker få någon annan att skriva koden

Ej kompilerat, ej testat, finns säkert fel. Men principen.
Dela upp i fristående rutiner som sköter sej själva.
Kod: Markera allt
#include <TaskScheduler.h>
byte sensorOK;
String sensorValue;
// Callback methods prototypes
void displayRoutine();
void readSensor();
void readButtonsandControl();
//Tasks
Task t1(500, TASK_FOREVER, &displayRoutine);
Task t2(200, TASK_FOREVER, &readSensor); // 5 ggr i sekunden
Task t3(50, TASK_FOREVER, &readButtonsandControl);
Scheduler Runner;
void setup()
{
sensorOK = TRUE;
lcd.begin(20, 4);
lcd.clear();
Runner.init();
Runner.addTask(t1);
Runner.addTask(t2);
Runner.addTask(t3);
t1.enable();
t2.enable();
t3.enable();
Serial.print("@254PR3?;FF"); //Skicka förfråga till sensorn om vakuumnivå 5 ggr i sekunden (klarar 10 ggr men tyvärr inte displayen)
//och få tillbaka tex @254ACK6.48E-7;FF där siffrorna i mitten är värdet
}
void loop () {
runner.execute();
}
void displayRoutine()
{
lcd.clear();
lcd.print("Vacuum: ");
lcd.setCursor(16, 0);
lcd.print("Torr");
lcd.setCursor(8, 0);
if (sensorOK = TRUE) {
for (int mod = 7; mod < 14; mod++) { //Skriver enbart ut värdet tex 6.48E-7 på displayen
lcd.write(sensorValue[mod]);
}
} else {
lcd.write("Not OK");
}
}
void readSensor()
{
if (Serial.available()) { //Finns det någon data i den seriella bufferten?
sensorOK = TRUE;
sensorValue = Serial.readString();
} else {
sensorOK = FALSE;
}
Serial.print("@254PR3?;FF"); //Skicka förfråga till sensorn om vakuumnivå 5 ggr i sekunden (klarar 10 ggr men tyvärr inte displayen)
//och få tillbaka tex @254ACK6.48E-7;FF där siffrorna i mitten är värdet
}
void readButtonsandControl()
{
if (sensorOK == TRUE)
digitalWrite(13, LOW);
else
digitalWrite(13, HIGH);
}
Re: Ställa in tal display med knappar och jämföra detta med
Postat: 2 juli 2017, 08:34:16
av hawkan
När det gäller knapparna och som du vill ha det. Det blir ofta lite pilligt att få till det. Strategin är i alla fall att aldrig fastna i något vänteläge och att använda variabler, statevariabler brukar jag tänka men det är nog formellt fel benämning, för att hålla ordning på vilket läge/siffra man påverkar.
Nåt sånt här kanske?
Kod: Markera allt
void knappar_mm()
{
om pumppå {
om nivågivare == av
sätt på pumpen
annars
stäng av pumpen
}
if ingen knapp nedtryckt return
Om sifferknapp tryckt, siffraavintresse++ plus nån mod för att cirkulera mellan så många siffror du har
om siffraavintrresse > 0 && upp eller nerknapp tryckt
öka nämnda värde i en variabel som displayRoutine visar.
om siffraavintresses == 0 && onoffknapp tryckt
slå på/av pumpen
pumppå = not pumppå
}
Nåt sån't här skulle väl funka, den exakta logiken får du såklart fylla i. Man får ta sakerna en och en. Statevariabeln siffraavintresse håller ordning på vilken siffra man trycker på mellan de olika anropen av knappar_mm. knappar_mm kan anropas så ofta du vill. Kompliceringar kan vara att du får studs i kappen och/eller att du håller knappen intryckt så länge att det registeras som två eller flera tryck alternativt att rutinen loopar så snabbt att detta sker. Finns medel mot detta också.
Om du som här skiljer på visning av data och knappar och kontrollsaker så blir det lättare att hålla ordning på det. Den här rutinen ser till att fylla i de varibler som visas av displayRoutine. Fast det är såklart inget måste. Men smidigt.
Re: Ställa in tal display med knappar och jämföra detta med
Postat: 2 juli 2017, 23:14:57
av Henry
Jo något sådant, hur grunduppbyggnaden, eller vad man kall kalla det för, är jag dock rätt klar med i huvudet men det är mer hur programmeringen skall vara som så som är det stora problematiska just nu.
Problemet är att jag inte vet tex vad för funktioner och variabler som kan användas för tex knappdelen och jämförelsedelen men håller på för fullt att kolla upp och försöka hitta något liknande exempel på vad jag vill åstadkomma för att få idéer men det ser rätt mörkt ut än så länge.
Displaydelen att få bort ev flimmer och dylikt men framförallt delays, som jag vet jag att det inte kan användas om koden utvidgas, har jag rätt klart för mig att som du visade innan bara att lägga de enskilda delarna för displayen i tex 2 olika subrutiner som blir kallade vid rätt tillstånd på signalen från sensorn och det kan få ihop utan större problem.
Men jämförandet av värdena har jag dock tyvärr fått uppfattningen av att det var bra mer komplicerat är jag trodde/hoppade på.
Jag tänker dock i alla fall på en uppbyggnad liknande så här med knappdelen, som jag beskriver med egna ord:
Har den enklaste räknare/rutin för en knapp som räknar upp från 0 - 9 och tillbaka till 0 (ev inte även "ned" med en annan knapp bara för att göra det så enkelt som möjligt) och även visar innehållet på displayen så man får det bekräftat att det är rätt i rutinen då det är av yttersta vikt. Med en annan knapptryckning går man sedan till nästa siffra och samma där trycker in 0 - 9 och så vidare tills alla siffrorna är inmatade.
Jag tror att jag möjligtvis kunnat få ihop i alla fall en räknarrutin med en knapp då det borde finnas gott om exempel om liknande som jag kan få ideér från. Men hur sedan skifta till nästa rutin med en knapp vet jag dock ej men dessa delar är nog ändå det som jag oroar mig allra minst för.
Hur jag sedan skall göra (eller hur man nu kan/bör göra) för att kunna jämföra värdet i räkningsrutinerna med värdet från strängen från sensorn och se om det är högre eller lägre har jag inte ens en teori om.
Men i alla fall som exempel så har det i var och en av de 4 räkningsrutinerna (kan även göra så det bara blir 3 siffror från sensorn) följande siffror blivit inmatade:
2 6 8 5
På displayen läses värdet direkt från rutinerna och visas som vald vakuumnivån:
2.68E-5
Vid en annan knapptryckning bekräftas inmatningen och då tas värdet från den seriella bufferten som säg tex är @254ACK9.27E-3;FF och omvandlat blir
9.27E-3.
Nu skall siffrorna i var och en av räkningsrutinerna jämföras med var och en av siffrorna i strängen och på något vis se om hela värdet i sig (dock visserligen inte varje siffra för sig, det fungerar inte som jag ser det) är högre eller lägre än det sammanlagda som motsvarar värdet man matat in och sätta en utgång hög eller låg baserat på detta.
Men hur denna jämförelse kan göras rent programmässigt har jag absolut ingen som helst aning om ens mindre en teori. Har än så länge inte hittat något exempel på nätet om något i närheten där någon jämfört ett inmatat tal eller annat på en display på liknande sätt jag tänkt mig med ett tal från en sträng från Rx, det jag hittat än så länge vls, men den som söker han finner förhoppningsvis.
Re: Ställa in tal display med knappar och jämföra detta med
Postat: 3 juli 2017, 08:22:17
av hawkan
Undrar om du inte gör det svårare än det är?
2685 är ett tal, behandla det som det. Likaså är 9273 ett tal. Använd en unsigned int som typ och du kan göra direkta jämförelser if (2685 == 9273). Åtminstone så länge exponentdelen håller sej inom 0-9. Om det inte funkar så gör två tal av det. 268 är ett tal och 5 är ett tal. När du jämför behöver du jämföra if (268 == 927 && 5 == 3) (med variabler så klart). 2.68e-5 är även ett flyttal och likaså 9.27e-3, bara att använda. Men anar att det kan vara opraktiskt när du har fixa positioner och vill matcha mot displayen.
Det är också möjligt att använda en String. Funkar utmärkt att göra direkt jämförelse mellan två String if (String("2685") == String(9273")).
Det kanske är smidigast faktiskt. Eller om du vill spara "9.27E-3" i en String och likaså göra inmatningen till "2.68E-5". En konvention hur du sparar det numeriska värdet i String behöver du ha i alla fall. Hmm, ska du göra jämförelser > eller < får du nog jobba med tal. Fast se toInt() nedan.
Dra ur det numeriska värdet från seriella indata först genom att isolera det med string2=value.substring(7,14).
Numeriskt värde kan du få genom lite pill t ex int tal = string2.substring(0,1).toInt()*1000+string2.substring(2,4).toInt()*10+string2.substring(6,7).toInt()
"9.27E-5" borde bli talet 9275 med detta. Göra om till String med String str(9275).
Re: Ställa in tal display med knappar och jämföra detta med
Postat: 3 juli 2017, 09:51:21
av Wedge
Kom ihåg att aldrig ha flyttal och exakt likhet i en jämförelse. Det är att be om problem.
Re: Ställa in tal display med knappar och jämföra detta med
Postat: 3 juli 2017, 15:28:09
av Henry
Ett rent tex 9273 från sensorn är väl inte att beteckna som ett flyttal? Det är väl mer vid matematiska beräkningar som något sådan kan förekomma med decimaler och avrundningar från ett tal och så? Värdet från sensorn och genom hela operationen sedan är ju statiskt hela vägen så att säga.
---
Undrar om du inte gör det svårare än det är?
Ingen aning, jag hoppas på det så det kan bli lättare.
2685 är ett tal, behandla det som det. Likaså är 9273 ett tal.
Ok, hänger med.
Använd en unsigned int som typ och du kan göra direkta jämförelser if (2685 == 9273). Åtminstone så länge exponentdelen håller sej inom 0-9.
Ok, hänger med hyfsat även här.
Exponentdelen håller sig inom 0 - 9, dock går den tyvärr mellan negativt och positivt i övre delen av vakuumnivån.
Vanligt lufttryck är tex runt 7.60E+3 Torr och då ett plustecken, alternativt inget tecken alls där från sensorn, kommer inte ihåg vad den visar här vid övergången kan hända den inte visar något tecken alls där. Vid grovvakuum och lägre så går den sista siffran dock till slut till negativt, stöter detta på några andra problem mer än jag förmodligen måste göra det i två delar?
Om det inte funkar.. m.m.
En hel del intressanta bra konkreta tips där som jag till stor del kopplar och säkert kan bygga vidare på, tackar!
Re: Ställa in tal display med knappar och jämföra detta med
Postat: 3 juli 2017, 19:11:23
av Icecap
Det kan gå mycket enkelt att ta värdet med exponent och fixa till ett heltal.
Att exponenten är negativ betyder ju bara att man kan använda en minsta enhet på t.ex. 1E-9.
Det viktiga är att talen kan jämföras rakt av och att de därför har samma basvärde.
Re: Ställa in tal display med knappar och jämföra detta med
Postat: 3 juli 2017, 19:38:50
av Henry
Tänker rent programmeringsmässigt nu för det går väl inte som jag förstått det att ha ett värde sparat tex som 224-2 utan det måste vara ett helt negativt tal så att säga och således tvådelat med exponenten för sig?
Re: Ställa in tal display med knappar och jämföra detta med
Postat: 3 juli 2017, 20:57:43
av hawkan
Om du bara ska använda givarens värde för att sätta på eller av en pump vid ett visst värde fungerar det bra med float eller double. Man är inte intresserad av om de två talen är samma, bara om det är mer eller mindre än det givna värdet.
Får säga att lägga exponenten sist i en String som jag gjorde tidigare var en rätt dålig idé. Jämförelser blir inte lätt. Glöm det, det var ett exempel.
Re: Ställa in tal display med knappar och jämföra detta med
Postat: 3 juli 2017, 21:41:53
av Icecap
Om xxx,xxxE-9 är lägsta värde kan man enkelt beskriva det som xxxxxx.
Yyy,yyyE-6 blir då yyyyyy000.
Dessa värden kan enkelt jämföras.