variabeldata -> procent-tal i LCD ?

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Användarvisningsbild
JimmyAndersson
Inlägg: 26578
Blev medlem: 6 augusti 2005, 21:23:33
Ort: Oskarshamn (En bit utanför)
Kontakt:

variabeldata -> procent-tal i LCD ?

Inlägg av JimmyAndersson »

Som rubriken lyder:
Hur gör jag enkelt för att skicka innehållet i en variabel (i detta fall ett procenttal) till en LCD?

Gör jag såhär:

Lite MikroBasic-kod:
pot = Adc_Read(2) + 1 ' Läser av en potentiometer som test.
resultat = (pot / 256) * 100 ' Räknar ut procenten...
skriv_ut(resultat) ' Skickar resultatet till en rutin som skriver ut till LCD'n.

..så skickar den ju ut ett tecken som motsvarar ASCII-tecknet av innehållet i variabeln 'resultat'.
Sätter jag citat-tecken runt variabeln så skriver den ju ut ordet 'Resultat'... :)

Först tänkte jag plocka ut siffra för siffra i variabeln, omvandla dessa till motsvarande ASCII-kod och sedan skicka ut dem till LCD'n en och en. Men nog borde det finnas ett lättare sätt? ...eller är detta det lättaste/enda sättet? :)



edit: Gjorde några formler som plockar ut hundratal, tiotal och ental:
Exemplet är baserat på att resultat = 128 och med hopp om att MikroBasic ignorerar decimaler... :roll:

hundratal = resultat / 100 ' = 1
tal = (resultat - (hundratal * 100)) ' = 28
ental = tal - ((tal / 10) * 10) ' = 8
tiotal = (tal - ental) / 10 ' = 2

Kanske får göra en grejj som kollar om talet är tillräckligt stort för att kunna divideras med 100 och 10. Annars blir det nog lite konstiga resultat. (Har inte räknat på det ännu.)
Med tanke på att klockan är 07:22 så kan möjligen något fel ha smugit sig in i formlerna.

Men som sagt: Enklare/smartare tips mottages gärna.



Info:
LCD: 2*16 Sharp LM16A211
PIC: 18LF2320
Språk: MikroBasic

edit: Ändrade rubriken en aning...
Senast redigerad av JimmyAndersson 7 november 2005, 02:28:48, redigerad totalt 1 gång.
Användarvisningsbild
karlstedt
EF Sponsor
Inlägg: 966
Blev medlem: 14 oktober 2003, 16:55:23
Ort: Lund
Kontakt:

Inlägg av karlstedt »

I C finns det en funktion för detta som heter itoa(), den förvandlar just ett heltal till en sträng. Vet dock inte om det finns motsvarande i MikroBasic.
macgyver
Inlägg: 321
Blev medlem: 8 juni 2005, 00:24:09
Ort: Göteborg
Kontakt:

Inlägg av macgyver »

kommer ihåg från den gammla goda tiden då man använde qbasic, då kunde man göra om nummer till textsträngar med: string$ = str$(nummer)

så i ditt fall kanske skriv_ut(str$(resultat)) kanske fungerar?
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

Har du letat alls i manueln ?

Jag laddade just ner "User Manual" och efter 10-15 sek hittade jag funktionerna ByteToStr, ShortToStr, WordToStr, IntToStr, LongIntToStr och FloatToStr. Sidorna 265-268.
Användarvisningsbild
bengt-re
EF Sponsor
Inlägg: 4829
Blev medlem: 4 april 2005, 16:18:59
Skype: bengt-re
Ort: Söder om söder
Kontakt:

Inlägg av bengt-re »

serout a1,i9600,[dec temp,10,13]
Funkar väl ?
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

Var hittade du "serout" ?
Har sökt i MikroBasic manueln, men där finns det inte med...
Och, vad är kopplingen mellan en fuktion för seriekommunikation och en standard LCD ?
Användarvisningsbild
bengt-re
EF Sponsor
Inlägg: 4829
Blev medlem: 4 april 2005, 16:18:59
Skype: bengt-re
Ort: Söder om söder
Kontakt:

Inlägg av bengt-re »

A, men menade bara pricipen, råkade vara en seriedrivare, men samma formatering fungerar på LCD-liben också. Annars fullt möjligt att mjukvarumässigt BCD-koda sina binärvärden också. Antigen skriva rutinen själv eller hitta på nätet. Inte första gången någon vill göra om ett binärtal till BCD-ASCII....
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

> samma formatering fungerar på LCD-liben också.

Möjligt, jag har sökt fram och tillbaka i manualen men förstår inte hur.
Skit samma, det är inte mitt "case"... :-)

> Inte första gången någon vill göra om ett binärtal till BCD-ASCII....

Kanske därför som de olika "...ToStr" funktionerna finns ?
Och de exempel som finns i kapitlet om LCD libarna använder "...ToStr" funktionerna.
Användarvisningsbild
Greve Hamilton
EF Sponsor
Inlägg: 544
Blev medlem: 4 september 2004, 15:03:35
Ort: GBG

Inlägg av Greve Hamilton »

Som Sodjan säger: det är XToStr som gäller.

Exempel:

Kod: Markera allt

pot = Adc_Read(2) + 1 ' Läser av en potentiometer som test.
resultat = (pot / 256) * 100 ' Räknar ut procenten...
ByteToStr(resultat, resultat_ut) ' Förutsatt att resultat är byte eller word.
skriv_ut(resultat_ut)
Användarvisningsbild
JimmyAndersson
Inlägg: 26578
Blev medlem: 6 augusti 2005, 21:23:33
Ort: Oskarshamn (En bit utanför)
Kontakt:

Inlägg av JimmyAndersson »

>Har du letat alls i manueln ?
sodjan: Jepp! :) Jag hittade också bl.a ByteToStr, men det fungerade inte alls.


Jag får bara ut en svart fyrkant (motsvarar 255 decimalt) på displayen.

Först lite kod. Initieringen är bortklippt, men den fungerar. Jag använder inte LCD-library, utan kör med registren direkt.

Kod: Markera allt

'Lite globala grejjer...
dim tid as byte
dim resultat as byte
dim resultat_ut as string[3]
dim pot as byte

---
**Här ligger normalt init-proceduren som bl.a initierar LCD'n**
---

sub procedure skriv_ut(dim value as string[3])
  tid = 20
  PORTB = value
  PORTC.2 = 1 ' E
  vdelay_ms(tid)
  PORTC.2 = 0
  vdelay_ms(tid)

  delay_ms(200)
end sub


main:
init

  while true
  'Omvandla värdet (0-255) till procent (0-100)
  pot = Adc_Read(2) + 1
  'resultat = ((pot / 256) * 100)
  resultat = 65
  ByteToStr(resultat, resultat_ut)
  
  skriv_ut(resultat_ut)

  ' skriv_ut(37) 'Procenttecken

---
**Här ligger lite kod för rensa skärmen**
---

  wend
Problemet (för mig iallafall) är att om jag kör med 'ByteToStr' så blir ju 'resultat_ut' en sträng med tre tecken. (Det blir två blanksteg och en etta om 'resultat = 1'.) Då måste jag ju dimensionera 'value' (som skickar strängen till LCDn) som en sträng och då fungerar det inte. Dimensionerar jag 'value' och 'resultat_ut' som byte så blinkar 16st svarta fyrkanter på översta raden i LCD'n.

Kodexemplen ni gav, är det så ni brukar göra? Vad har jag gjort annorlunda eftersom det inte fungerar?


sodjan: Du skrev 'de exempel som finns i kapitlet om LCD libarna använder "...ToStr" funktionerna." '

Varken i LCD library eller något LCD-exempel används "...ToStr". Var hittade du de exemplen?

I mitt MikroBasic ser ett exempel för LCD library ut såhär:

Kod: Markera allt

dim text as char[20]

main:
  TRISB = 0                   ' PORTB is output
  Lcd_Init(PORTB)             ' Initialize LCD on PORTB
  Lcd_Cmd(Lcd_CURSOR_OFF)     ' Turn off cursor
  text = "mikroElektronika"
  Lcd_Out(1, 1, text)         ' Print text at LCD
end.
Inget om "ToStr" alltså...
Användarvisningsbild
Greve Hamilton
EF Sponsor
Inlägg: 544
Blev medlem: 4 september 2004, 15:03:35
Ort: GBG

Inlägg av Greve Hamilton »

Testa att sätta "pot" och "resultat" till word, och använd sedan WordToStr. Och kanske resultat_ till char. Det fungerar för mig, iaf.

Nu när jag tittar igen på exemplet jag skriv tidigare, så är jag inte helt bombsäker på att det kommer att fungera.

Detta är jag säker på fungerar:

Kod: Markera allt

program adctest

dim value, value_100 as word
dim value_str as char[10]

main:

ADCON1 = $80
TRISA = 1
TRISB = 0
TRISC = 0
TRISD = 0
TRISE = 0

Lcd8_Config(PORTD,PORTB,0,2,1,7,6,5,4,3,2,1,0)
Lcd8_Cmd(Lcd_Cursor_Off)
Lcd8_Cmd(Lcd_Clear)

While TRUE

value = ADC_Read(2)
value_100 = value + 100

WordToStr(value_100, value_str)
Lcd8_Out(2, 1, value_str)

Wend
End.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

> sub procedure skriv_ut(dim value as string[3])
> tid = 20
> PORTB = value

Det här vet jag inte hur det är tänkt.
"value" är ju en sträng med *tre* bytes, men PORTB kan är ju enbart en enda byte. Du måste skriva en byte i taget från "value" till PORTB (d.v.s till LCDn).

Antagligen fungerar något i stil med :

PORTB = value[0]
PORTC.2 = 1 ' E
vdelay_ms(tid)
PORTC.2 = 0
vdelay_ms(tid)

PORTB = value[1]
PORTC.2 = 1 ' E
vdelay_ms(tid)
PORTC.2 = 0
vdelay_ms(tid)

PORTB = value[2]
PORTC.2 = 1 ' E
vdelay_ms(tid)
PORTC.2 = 0
vdelay_ms(tid)

Se sid 59.

> Då måste jag ju dimensionera 'value' (som skickar strängen till LCDn) som en sträng och då fungerar det inte.

Men felet är i "skriv_ut" som inte hanterar parametern på rätt sätt.
*Någonstans* måste du ju hur som helst omvandla din binära variabel till en sträng, så "skriv_ut" måste hur du än gör kunna hantera det.

Det exempel du visar skriver ju inte ut några binära (int eller liknande) värden, så varför skulle man behöva någon "...ToStr" där ??

> Varken i LCD library eller något LCD-exempel används "...ToStr". Var hittade du de exemplen?

I exemplet till "FloatToStr" på sidan 268.

Hur som helst, på *något* sätt måste du ju i alla fall konvertera ditt binära värde till motsvarande sträng av ASCII-tecken och skriva dom ett-och-ett till LCDn. Om du gör det med "egen" kod eller "...ToStr" funktionerna spelar väll mindre roll.
Användarvisningsbild
JimmyAndersson
Inlägg: 26578
Blev medlem: 6 augusti 2005, 21:23:33
Ort: Oskarshamn (En bit utanför)
Kontakt:

Inlägg av JimmyAndersson »

sodjan:
>I exemplet till "FloatToStr" på sidan 268.

Nu förstår jag varför jag inte hittade det: Jag hade inte "rätt" manual, min hade runt 160sidor. Har laddat hem den nya nu. :)

Du har helt rätt (förstås) i att PORTB bara kan hantera en byte. Inte konstigt att det blir fel där. Ska bygga om koden så det blir rätt.

Greve Hamilton: Tack för koden! Jag kör för tillfället utan LCDlibrary-funktionerna, men jag sparar din kod för framtida projekt. :)
Användarvisningsbild
JimmyAndersson
Inlägg: 26578
Blev medlem: 6 augusti 2005, 21:23:33
Ort: Oskarshamn (En bit utanför)
Kontakt:

Inlägg av JimmyAndersson »

Sådärja, nu fungerar det mycket bättre.
Har ett litet problem kvar, men vi tar koden först:

Kod: Markera allt

dim tid as byte
dim resultat as word
dim resultat_ut as string[3]
dim pot as byte
dim tecken as byte

--- 
**Här ligger normalt init-proceduren som bl.a initierar LCD'n** 
--- 

sub procedure skriv_ut(dim value as string[3])
dim antal as byte
  tid = 20
  antal = length(value) - 1
 for tecken = 0 to antal
  PORTB = value[tecken]
  PORTC.2 = 1 ' E
  vdelay_ms(tid)
  PORTC.2 = 0
  vdelay_ms(tid)
 next tecken
  PORTB = 37 ' Procenttecken
  PORTC.2 = 1 ' E
  vdelay_ms(tid)
  PORTC.2 = 0
  vdelay_ms(tid)
end sub

main:
init

  while true
  'Omvandla värdet (0-255) till procent (0-100)
  pot = Adc_Read(0)
  resultat = (((pot + 1) * 100) / 256)
  ByteToStr(resultat, resultat_ut)
  
  skriv_ut(resultat_ut)
  

--- 
**Här ligger lite kod för flytta markören till position 1:1 på LCD'n** 
--- 

  wend
end.
(Poten är kopplad till AN0 med "referenser" från Vdd och Vss.)

Och så till problemet: När man skruvar långsamt på poten från ena sidan till andra så går den från 0 - 100% fyra gånger. Min formel för att räkna ut procenten stämmer. Variabeln 'pot' ger värden mellan 0 och 255.

Anledningen till att jag gör resultat = (((pot + 1) * 100) / 256) istället för resultat = (((pot + 1) / 256) * 100) är för att ifall pot + 1 = 1 och jag skulle dela med 256 så blir det 0,00390625. :shock:
Om jag däremot först tar pot + 1 = 1 * 100 så blir det förstås 100. Trodde det skulle ställa till det när jag körde med pot + 1 = 256 * 100, men varken MikroBasic eller PIC'en protesterade.

Jag vet inte riktigt varför jag displayen stegar från 0 - 100% fyra gånger.
Hoppas att någon har någon idé varför det blir såhär. :roll:
(Det *går* visserligen att lösa hårdvarumässigt men går det att fixa till i koden så gör jag hellre det.)


Men annars fungerar det :tumupp: :idea: och jag är :) .
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

ADC'n ger värden från 0 - 1023 (alltså 1024 steg eller 2^^10 steg, det är ju en 10-bitars ADC).

Antagligen har det något med att göra att du har 256 istället för 1024 i dina beräkningar...
Skriv svar