Sida 1 av 2

variabeldata -> procent-tal i LCD ?

Postat: 6 november 2005, 06:02:47
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...

Postat: 6 november 2005, 09:07:02
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.

Postat: 6 november 2005, 10:05:28
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?

Postat: 6 november 2005, 12:30:15
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.

Postat: 6 november 2005, 12:36:57
av bengt-re
serout a1,i9600,[dec temp,10,13]
Funkar väl ?

Postat: 6 november 2005, 13:15:20
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 ?

Postat: 6 november 2005, 13:22:08
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....

Postat: 6 november 2005, 13:41:42
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.

Postat: 6 november 2005, 14:00:03
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)

Postat: 6 november 2005, 19:55:57
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å...

Postat: 6 november 2005, 21:57:29
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.

Postat: 6 november 2005, 22:01:01
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.

Postat: 7 november 2005, 00:34:59
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. :)

Postat: 7 november 2005, 02:20:49
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 :) .

Postat: 7 november 2005, 09:59:35
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...