Open sorf opened 5 months ago
In 8-bit mode (code here, wokwi-simulation), it works on the HW LCD from the Arduino starter kit, but not in the simulation.
In the simulation, it gets stuck at something like this:
It seems i'm encountering the same issue. Arduino code works in 4 bit mode but the tinygo example isn't working on it. I'm attempting to construct a setup for 8 bit mode, will update here with my findings.
The display I'm currently testing with is an older VFD type display. It does work with arduino code, when i write one character at a time and introduce a small delay between writes.
I will come back and add to this issue a test on a more modern display when i get around to it.
Seems I'm getting panic on lcd.Display() with the following code, in 8 bit mode
//main.go
package main
import (
"machine"
"time"
"tinygo.org/x/drivers/hd44780"
)
func main() {
machine.UART0.Configure(machine.UARTConfig{TX: machine.UART_TX_PIN, RX: machine.UART_RX_PIN, BaudRate: 9600})
machine.UART0.Write([]byte("starting up...\n"))
led := machine.LED
led.Configure(machine.PinConfig{Mode: machine.PinOutput})
machine.UART0.Write([]byte("configured LED\n"))
rw := machine.NoPin
rs := machine.D2
en := machine.D3
d4 := machine.D4
d5 := machine.D5
d6 := machine.D6
d7 := machine.D7
d8 := machine.D8
d10 := machine.D10
d11 := machine.D11
d12 := machine.D12
contrast := machine.D9
contrast.Configure(machine.PinConfig{Mode: machine.PinOutput})
contrast.High()
machine.UART0.Write([]byte("set contrast\n"))
lcd, err := hd44780.NewGPIO8Bit(
[]machine.Pin{d12,d11,d10,d8,d7,d6,d5,d4},
rs,
en,
rw,
)
if err != nil {
machine.UART0.Write([]byte("error initializing lcd NewGPIO8Bit \n"))
machine.UART0.Write([]byte(err.Error()+"\n"))
}
machine.UART0.Write([]byte("initialized lcd\n"))
err = lcd.Configure(hd44780.Config{
Width: 16,
Height: 1,
CursorOnOff: true,
CursorBlink: false,
})
if err != nil {
machine.UART0.Write([]byte("error configuring lcd\n"))
machine.UART0.Write([]byte(err.Error()+"\n"))
}
machine.UART0.Write([]byte("configured lcd\n"))
machine.UART0.Write([]byte("testing lcd.Write\n"))
lcd.Write([]byte("a"))
machine.UART0.Write([]byte("testing lcd.Display\n"))
time.Sleep(1000)
err = lcd.Display()
if err != nil {
machine.UART0.Write([]byte("error initializing lcd\n"))
machine.UART0.Write([]byte(err.Error()+"\n"))
}
for {
led.Low()
machine.UART0.Write([]byte("LED Low\n"))
time.Sleep(time.Millisecond * 1000)
led.High()
machine.UART0.Write([]byte("LED High\n"))
time.Sleep(time.Millisecond * 100)
}
}
a serial monitor program which accompanies this
// mon.go
package main
import (
"fmt"
"log"
"github.com/tarm/serial"
)
func main() {
port, err := serial.OpenPort(&serial.Config{Name: "/dev/ttyUSB0", Baud: 9600})
if err != nil {
log.Fatalf("serial.OpenPort: %v", err)
}
defer port.Close()
buf := make([]byte, 128)
for {
n, err := port.Read(buf)
if err != nil {
log.Fatalf("port.Read: %v", err)
}
fmt.Print(string(buf[:n]))
}
}
Testing output
$ tinygo flash -target=arduino -port=/dev/ttyUSB0 main.go && go run mon.go
avrdude: AVR device initialized and ready to accept instructions
avrdude: device signature = 0x1e950f (probably m328p)
avrdude: Note: flash memory has been specified, an erase cycle will be performed.
To disable this feature, specify the -D option.
avrdude: erasing chip
avrdude: processing -U flash:w:/tmp/tinygo1630339240/main.hex:i
avrdude: reading input file /tmp/tinygo1630339240/main.hex for flash
with 6485 bytes in 1 section within [0, 0x1954]
using 51 pages and 43 pad bytes
avrdude: writing 6485 bytes flash ...
Writing | ################################################## | 100% 1.08 s
avrdude: 6485 bytes of flash written
avrdude: verifying flash memory against /tmp/tinygo1630339240/main.hex
Reading | ################################################## | 100% 0.83 s
avrdude: 6485 bytes of flash verified
avrdude done. Thank you.
starting up...
configured LED
set contra�starting up...
configured LED
set contrast
initialized lcd
configured lcd
testing lcd.Write
testing lcd.Display
panic: runtime error: index out of range
https://github.com/tinygo-org/drivers/assets/36607567/77d8884a-de30-42bd-babe-fac7b4885ade
Seems I'm getting panic on lcd.Display() with the following code, in 8 bit mode
If this panic is without it, could you please try with the proposed fix (#647) for this issue? It should be just a matter of adding:
replace tinygo.org/x/drivers => github.com/sorf/tinygo-drivers v0.0.0-20240126073429-67f5ced56e82
to the go.mod
(such as here) and go mod tidy
.
For me the the fix worked in both 4-bit and 8-bit mode with the LCD from the Arduino starter kit and the virtual one on wokwi.com.
There were a few issues with the code in my previous comment, but after fixing those I could never get past panic: runtime error: index out of range
After many attempts, i ended up copying the whole driver into the modified example code. I was then able to just create a GPIO and use write8BitMode as follows
package main
import (
"errors"
"io"
m "machine"
"time"
// "tinygo.org/x/drivers/hd44780"
)
func main() {
m.UART0.Configure(m.UARTConfig{TX: m.UART_TX_PIN, RX: m.UART_RX_PIN, BaudRate: 9600})
m.UART0.Write([]byte("starting up...\n"))
led := m.LED
led.Configure(m.PinConfig{Mode: m.PinOutput})
m.UART0.Write([]byte("configured LED\n"))
cont := m.D9
cont.Configure(m.PinConfig{Mode: m.PinOutput})
cont.High()
m.UART0.Write([]byte("set contrast\n"))
m.Serial.Configure(m.UARTConfig{BaudRate: 9600})
m.D12.Configure(m.PinConfig{Mode: m.PinOutput})
m.D11.Configure(m.PinConfig{Mode: m.PinOutput})
m.D10.Configure(m.PinConfig{Mode: m.PinOutput})
m.D8.Configure(m.PinConfig{Mode: m.PinOutput})
m.D7.Configure(m.PinConfig{Mode: m.PinOutput})
m.D6.Configure(m.PinConfig{Mode: m.PinOutput})
m.D5.Configure(m.PinConfig{Mode: m.PinOutput})
m.D4.Configure(m.PinConfig{Mode: m.PinOutput})
m.D3.Configure(m.PinConfig{Mode: m.PinOutput})
m.D2.Configure(m.PinConfig{Mode: m.PinOutput})
//rw.Configure(m.PinConfig{Mode: m.PinOutput})
//rw.Low()
gpio := GPIO{
dataPins: []m.Pin{m.D12, m.D11, m.D10, m.D8,m.D7, m.D6, m.D5, m.D4},
en: m.D3,
rs: m.D2,
rw: m.NoPin,
}
gpio.write = gpio.write8BitMode
gpio.read = gpio.read8BitMode
m.UART0.Write([]byte("initialized gpio\n"))
m.UART0.Write([]byte("testing gpio.write8BitMode\n"))
for _, b := range []byte("ABCDEFGHIJKLMN0PQRSTUVWXYZ") {
gpio.write8BitMode(b)
time.Sleep(time.Millisecond * 100)
}
for {
led.Low()
m.UART0.Write([]byte("LED Low\n"))
time.Sleep(time.Millisecond * 1000)
led.High()
m.UART0.Write([]byte("LED High\n"))
time.Sleep(time.Millisecond * 100)
}
}
and it works! (the characters need to be remapped)
perhaps there can be a more generic way of integrating this workaround into an example to support older displays. If the GPIO struct fields were exported, it would be possible to do this.
I can confirm now that the example driver works for me in both 4 and 8 bit mode with a modern 16X2 LCD. I had misconfigured the contrast PWM, which was not actually part of that example. After adding that, the text became visible.
The code exhibiting the problem is pretty much a hello-world type (from here)
It happens with latest version (
v0.26.0
), on both:The easiest way to reproduce the issue is with a virtual circuit on wokwi.com (such as this one), by pressing
F1
there, then selectingUpload Firmware and Start Simulation
and uploading thetinygo
built hex file. The mis-behavior is of random "gibberish" showing up on the LCD.Th expected behavior of the virtual circuit should be like exhibited by this one - programmed with the Arduino LiquidCrystal library.
Possibly related to #380?