Jetson Nano devkit works with resistive 4" Waveshare touchscreen - success story

Hi all,

after several days of struggling I finally have Jetson Nano devkit working with XPT2046 based Waveshare 4inch HDMI LCD (resistive touchscreen, SKU 12030). More, there is no need a single small solder!

Prerequisites:

Steps from scratch (a bit excessive, omit unneeded steps at your own):

  1. Plug the display onto the J41 header, starting from pin 1. Thank you Nvidia guys who made it compatible with RasPi!
  2. Connect Jetson and display with HDMI cable.
  3. Falsh a 32+Gb SD card with balenaEtcher as described in Jetson Nano quick start. (I had to unzip sd_blob_b01.img from jetson-nano-developer-kit-sd-card-image.zip first), insert the card into Nano
  4. Power up the board. At this point the screen will show Ubuntu setup. Follow the wizard, reboot as needed. Set up networking for future downloads.

apt update && apt upgrade

  1. git clone https://github.com/JetsonHacksNano/buildKernelAndModules.git

cd buildKernelAndModules

  1. Edit getKernelSources.sh: set L4T_TARGET=“32.4.3 (as of Aug 2020)

./getKernelSources.sh

As expected, this will download kernel sources :)
9.

apt install libncurses-dev && ./editConfig.sh

In Device drivers - Input device suppiort - Touchscreens select “ADS7846/TSC2046/AD7873 and AD(S)7843 based touchscreens” and mark it with asterisk (driver built into kernel). Exit, exit, exit, exit, yes. Way too boring :)
10.

./makeKernel.sh

  1. In the case of error-free build,

./copyImage.sh

— At this point we have a new kernel built abd installed in system. —
— Now let’s update device tree —
12. (This step is best of all done over ssh, in extended window)

sudo /opt/nvidia/jetson-io/jetson-io.py
Configure 40-pin expansion header
Mark “spi1” with asterisk
Back
Save and exit without rebooting
At this step copy resulting file location. It will be something like /boot/tegra210-p3448-0000-p3449-0000-b00-user-custom.dtb

  1. Decompile device tree:

dtc -O dts -o tegra.dts /boot/tegra210-p3448-0000-p3449-0000-b00-user-custom.dtb

  1. Replace
           spi@1 {
                    compatible = "spidev";
                    reg = <0x1>;
                    spi-max-frequency = <0x1f78a40>;

                    controller-data {
                            nvidia,enable-hw-based-cs;
                            nvidia,rx-clk-tap-delay = <0x7>;
                    };
            };

with

          spi@1 {
                compatible = "ti,ads7846";
                reg = <0x1>; // CS1 of SPI
                spi-max-frequency = <0x7a120>;
                nvidia,enable-hw-based-cs;
                nvidia,rx-clk-tap-delay = <0x7>;
                interrupt-parent = <0x56>; // phandle of "gpio@6000d000"
                interrupts = <0x0d 0x1>; // pin 22 is gpio13, IRQ13
                pendown-gpio = <0x56 0x0d 0x0>; 
                vcc-supply = <0x47>; // phandle of "regulator@2"
                //ti,swap-xy = <0x1>; // uncomment to swap axes 
                ti,x-min = [00 00];
                ti,x-max = [1f 40];
                ti,y-min = [00 00];
                ti,y-max = [12 c0];
                ti,x-plate-ohms = [00 28];
                ti,pressure-max = [00 ff];
                wakeup-source;
                controller-data {
                    nvidia,cs-setup-clk-count = <0x1e>;
                    nvidia,cs-hold-clk-count = <0x1e>;
                    nvidia,rx-clk-tap-delay = <0x1f>;
                    nvidia,tx-clk-tap-delay = <0x0>;
                };
            };
  1. Build device tree blob then copy it into /boot. This is where you will need the loooong previously copied file name:

dtc -O dtb tegra.dts -o tegra210-p3448-0000-p3449-0000-b00-user-custom.dtb
cp /boot/tegra210-p3448-0000-p3449-0000-b00-user-custom.dtb /boot/tegra210-p3448-0000-p3449-0000-b00-user-custom.dtb.orig
cp tegra210-p3448-0000-p3449-0000-b00-user-custom.dtb /boot

apt install xinput_calibrator

  1. Reboot.
  2. (from screen and keyboard, use Ctrl+Alt+T to open terminal)

xinput_calibrator

Enjoy :)

V_20200831_180430

3 Likes

Thanks for your kind share!

1 Like

Hello.
Thank you for letting me know in detail how to use the touchscreen.
I am trying to use a 3.5inch HDMI LCD, 480x320, IPS touchscreen on a jetson xavier nx.

It was the same as the method you informed, and spi1 was modified as follows to suit Jetson Xavier NX.
spi@1 {
compatible = “ti,ads7846”;
reg = <0x1>; // CS1 of SPI
spi-max-frequency = <0x7a120>;
nvidia,enable-hw-based-cs;
nvidia,rx-clk-tap-delay = <0x10>;
interrupt-parent = <0x13>; // phandle of "gpio@2200000"
interrupts = <0x42 0x1>;
pendown-gpio = <0x13 0x42 0x0>;
vcc-supply = <0x27>; // phandle of "regulator@101"
//ti,swap-xy = <0x1>; // uncomment to swap axes
ti,x-min = [00 00];
ti,x-max = [1f 40];
ti,y-min = [00 00];
ti,y-max = [12 c0];
ti,x-plate-ohms = [00 28];
ti,pressure-max = [00 ff];
wakeup-source;
controller-data {
nvidia,cs-setup-clk-count = <0x1e>;
nvidia,cs-hold-clk-count = <0x1e>;
nvidia,rx-clk-tap-delay = <0x1f>;
nvidia,tx-clk-tap-delay = <0x0>;
};
};

But When I try ‘dmesg | grep spi’, the following error message appears.
Do you know anything about this error message?


Thank you.

One thing I can expect is wrong interrupt. In this case you receive an interrupt from a different device (e.g. USB or LAN), which results in unexpected transfer start and subsequent failure (while device is seen on SPI). How did you choose settings for your “interrupts” line?

The changes I made are as follows.

nvidia,rx-clk-tap-delay = <0x7>; -> nvidia,rx-clk-tap-delay = <0x10>;
-> In xavier NX, the value of nvidia,rx-clk-tap-delay is 0x10, so it has been modified to 0x10.

interrupt-parent = <0x56>; // phandle of “gpio@6000d000” -> interrupt-parent = <0x13>;
-> Modified to phandle of gpio@2200000.

interrupts = <0x0d 0x1>; // pin 22 is gpio13, IRQ13 -> interrupts = <0x42 0x1>;
-> I didn’t understand about “// pin 22 is gpio13, IRQ13” (I’m not sure what value to put in jetson xavier NX).
So I checked IRQ13 of jetson nano.
The jetson nano’s IRQ13 was 6000c800.actmon.
As a result of checking the interrupt of jetson xavier NX, the IRQ corresponding to actmon in jetson xavier NX was 66.
So I changed 0x0d to 0x42.

pendown-gpio = <0x56 0x0d 0x0>; -> pendown-gpio = <0x13 0x42 0x0>;
-> 0x13 is thought to be’phandle of gpio@2200000’ and 0x42 is’interrupt’, so I modified it.

vcc-supply = <0x47>; -> vcc-supply = <0x27>;
-> Because the name of “regulator@2” is vdd-3v3-sys, I thought that “regulator@101” is suitable for jetson xaiver nx. (The name of “regulator@101” is vdd-3v3-cvb)

jetson nano -> pin 22 is gpio13,
jetson xavier nx -> pin22 is gpio481

Can I modify the following in jetson xavier nx?
interrupts = <0x01E1 0x1>
pendown-gpio = <0x13 0x01E1 0x0>;

I need to look into datasheets, but I’m out of office these days. Please wait
till next week - or just try :)

jetson nano ->> pin 22 is gpio13,
jetson xavier nx ->> pin22 is gpio481

_vNDF> Can I modify the following in jetson xavier nx?
_vNDF> interrupts = <0x01E1 0x1>
_vNDF> pendown-gpio = <0x13 0x01E1 0x0>;

_vNDF> —
_vNDF> Visit
_vNDF> Topic

_vNDF> or reply to this email to respond.

_vNDF> To unsubscribe from these emails, click
_vNDF> here
.

Yes, I will wait until next week. please check.
This is my progress so far.

I tried by changing below and the touchscreen device does not get caught.
Interrupt = <0x01E1 0x1>
pendown-gpio = <0x13 0x01E1 0x0>;

So I tried to modify it as below.
But I still get spi error.

Interrupt = <0xC1 0x1>
pendown-gpio = <0x13 0xC1 0x0>;
image

This is the result of checking sudo /sys/kernel/debug/gpio.

I am using a touchscreen on jetson nano.
The screen was rotated 90 degrees like the video you showed.
(setting - Display - clockwise)
And’ti, swap-xy = <0x1>; // Uncomment the comment for axis replacement.
However, the y-axis is touched in reverse (the x-axis is normally touched)

What should I do in order for the touch to proceed normally as in your video?

Did you use xinput_calibrator? It should solve the issue. You will need to try both combinations: with and without “’ti, swap-xy = <0x1>;”

Just stepped on the same rake and understood your possible problems. Sorry for late reply.
I used “touchcalib” script found somewhere:

device=(xinput_calibrator --list) device=(sed -n ‘s/.Device\s"(.)".*/\1/p’ <<< $device)

#reset xinput matrix
xinput set-prop “$device” ‘Coordinate Transformation Matrix’ 1 0 0 0 1 0 0 0 1

out=$(xinput_calibrator)

device_name=$(sed -n ‘s/.MatchProduct"\s"([0-9]).*/\1/p’ <<< $out)

wtot=$(sed -n ‘s/.max_x=([0-9])./\1/p’ <<< out) htot=(sed -n 's/.max_y=([0-9])./\1/p’ <<< $out)

minx=$(sed -n ‘s/.MinX"\s"([0-9])./\1/p’ <<< out) maxx=(sed -n 's/.MaxX"\s"([0-9])./\1/p’ <<< out) miny=(sed -n ‘s/.MinY"\s"([0-9])./\1/p’ <<< out) maxy=(sed -n 's/.MaxY"\s"([0-9])./\1/p’ <<< $out)

wtouch=$(bc <<< "$maxx - minx") htouch=(bc <<< “$maxy - $miny”)

c0=$(bc -l <<< "$wtot / wtouch") c1=(bc -l <<< "-$minx / wtouch") c2=(bc -l <<< "$htot / htouch") c3=(bc -l <<< “-$miny / $htouch”)

tf_matrix="$c0 0 $c1 0 $c2 $c3 0 0 1"

#alter the setting for now
xinput set-prop “$device” ‘Coordinate Transformation Matrix’ $tf_matrix

echo “To make this permanent, save the following content under ‘/etc/X11/xorg.conf.d/98-screen-calibration.conf’ or ‘/usr/share/X11/xorg.conf.d/98-screen-calibration.conf’”
echo “Section “InputClass””
echo " Identifier “calibration”"
echo " MatchProduct “$device”"
echo " Option “TransformationMatrix” “$tf_matrix”"
echo “EndSection”

After running this script I created /etc/X11/xorg.conf.d/98-screen-calibration.conf:

Section “InputClass”
Identifier “calibration”
MatchProduct “ADS7846 Touchscreen”
Option “SwapXY” “1”
Option “TransformationMatrix” “-2.17789372237546110132 0 1.04380047190189757734 0 1.31869126909068957884 -.07280117512123468217 0 0 1”
EndSection

My /etc/X11/xorg.conf is:

# Copyright © 2011-2013 NVIDIA CORPORATION. All Rights Reserved.

#
# This is the minimal configuration necessary to use the Tegra driver.
# Please refer to the xorg.conf man page for more configuration
# options provided by the X server, including display-related options
# provided by RandR 1.2 and higher.

# Disable extensions not useful on Tegra.
Section “Module”
Disable “dri”
SubSection “extmod”
Option “omit xfree86-dga”
EndSubSection
EndSection

Section “Device”
Identifier “Tegra0”
Driver “nvidia”
# Allow X server to be started even if no display devices are connected.
Option “AllowEmptyInitialConfiguration” “true”
Option “RandRRotation” “on”
Option “Rotate” “left”
EndSection

Section “Screen”
Identifier “Screen0”
Monitor “Monitor0”
SubSection “Display”
Viewport 0 0
Modes “480x800”
Depth 24
Virtual 480 800
Option “Rotate” “left”
EndSubSection
EndSection

Hope this helps.

One more issue from November 2020: actual L4T release is 32.4.4, and the sequence above did not work out for me. Meanwhile start with L4T32.4.3 image and do not run “apt upgrade” in the step 5 above.

Please comment if you made the stuff work on 32.4.4.

Hi, GrayDaemon
I am using a 3.5 inch HDMI LCD
However, the icon shakes when touched.
When I watch your video, the icon doesn’t seem to shake.
So I bought and tried a 4 inch HDMI LCD, but the results were the same.
Are you good at touch? Is there any problem with the icon shaking?
(The video is connected to the Raspberry Pi, but the same symptoms appear when connected to the Jetson Nano and run)
3.5LCD problem.zip (3.9 MB)

+) Do you know how to do it in L4T 32.4.4?
I initially tried it on L4T 32.4.4, but after failure it worked on L4T 32.4.3.

No, my icons don’t shake.
I can expect this due to screen setup and calibration. If you use touchcalib script above your transformation matrix coefficients must be relatively small, from 0.001 to 2-3. If you have values around 100 or even 1000 it leads to extreme sensivity of screen and any small EMI will cause sensor to produce shake or move.I this case you need to try the trick above with “ti, swap-xy = <0x1>;” and calibrate again, second calibration will probably give you small (correct) coefficients. Be sure to decompile, modify and recompile your existing DTB. After decompilation the string ’ti, swap-xy = <0x1>;’ will be missing from code, you need to add it manually.

Also check if your workplace has excessive EMI or power supply is not stable enough. This can also affect the screen behaviour.

Unfortunately, I don’t have enough time now to make this thing work on 32.4.4, in my test ADS7846 could not be probed. Need to dive into driver source code to figure out the issue. Last time it took few workdays to fix.

device=(xinput_calibrator --list) device=(sed -n ‘s/. Device\s"(. )".*/\1/p’ <<< $device)

#reset xinput matrix
xinput set-prop “$device” ‘Coordinate Transformation Matrix’ 1 0 0 0 1 0 0 0 1

out=$(xinput_calibrator)

device_name=$(sed -n ‘s/. MatchProduct"\s"([0-9] ).*/\1/p’ <<< $out)

wtot=$(sed -n ‘s/. max_x=([0-9] ). /\1/p’ <<< out) htot=(sed -n 's/. max_y=([0-9] ). /\1/p’ <<< $out)

minx=$(sed -n ‘s/. MinX"\s"([0-9] ). /\1/p’ <<< out) maxx=(sed -n 's/. MaxX"\s"([0-9] ). /\1/p’ <<< out) miny=(sed -n ‘s/. MinY"\s"([0-9] ). /\1/p’ <<< out) maxy=(sed -n 's/. MaxY"\s"([0-9] ). /\1/p’ <<< $out)

wtouch=$(bc <<< “$maxx - minx”) htouch=(bc <<< “$maxy - $miny”)

c0=$(bc -l <<< “$wtot / wtouch”) c1=(bc -l <<< “-$minx / wtouch”) c2=(bc -l <<< “$htot / htouch”) c3=(bc -l <<< “-$miny / $htouch”)

tf_matrix="$c0 0 $c1 0 $c2 $c3 0 0 1"

#alter the setting for now
xinput set-prop “$device” ‘Coordinate Transformation Matrix’ $tf_matrix

echo “To make this permanent, save the following content under ‘/etc/X11/xorg.conf.d/98->screen-calibration.conf’ or ‘/usr/share/X11/xorg.conf.d/98-screen-calibration.conf’”
echo “Section “InputClass””
echo " Identifier “calibration”"
echo " MatchProduct “$device”"
echo " Option “TransformationMatrix” “$tf_matrix”"
echo “EndSection”

How do I use the touchcalib script? (I am not sure how to use it)

Put this code into a file, make this file runnable, run it. It will load xinput_calibrator, touch screen 4 times as written there and touchcalib will show the transformation matrix and instructions to use it. Insert this matrix into /etc/X11/xorg.conf.d/98-screen-calibration.conf as written above.