Goodix GT1151 touch driver library for Arduino not working - arduino

I'm trying to get my "2.9inch Touch e-Paper Module for Raspberry Pi Pico" working that I bought from Amazon (wiki here. My main problem is that I'm not able to read data over i2c from the touchscreen and I've tried using the wiki's library with no luck.
GoodixGT1151.h
#ifndef GOODIX_GT1151_H
#define GOODIX_GT1151_H
#include <Arduino.h>
#include <Wire.h>
// I2C address of the Goodix GT1151 touchpanel
const uint8_t GT1151_I2C_ADDRESS = 0x5D;
// Register addresses for the Goodix GT1151 touchpanel
const uint8_t GT1151_REG_CMD = 0x8040;
const uint8_t GT1151_REG_DATA = 0x8140;
// Command values for the Goodix GT1151 touchpanel
const uint8_t GT1151_CMD_RESET = 0x01;
const uint8_t GT1151_CMD_IDLE = 0x04;
const uint8_t GT1151_CMD_READ_COORDS = 0x08;
// Size of the touch data array for the Goodix GT1151 touchpanel
const uint8_t GT1151_TOUCH_DATA_SIZE = 18;
// Maximum number of touch points supported by the Goodix GT1151 touchpanel
const uint8_t GT1151_MAX_TOUCH_POINTS = 5;
class GoodixGT1151 {
public:
// Struct for storing touch point data
struct TouchPoint
{
int16_t x;
int16_t y;
bool touched;
};
// Constructor
GoodixGT1151();
// Initialize the touchpanel
void begin();
// Reset the touchpanel
void reset();
// Put the touchpanel into idle mode
void idle();
// Read the current touch coordinates from the touchpanel
void readCoords(TouchPoint* points);
private:
// Write a command to the touchpanel
void writeCommand(uint8_t cmd);
// Read touch data from the touchpanel
void readTouchData(uint8_t* data);
};
#endif
GoodixGT1151.cpp
#include "GoodixGT1151.h"
GoodixGT1151::GoodixGT1151() {}
void GoodixGT1151::begin() {
Wire.begin();
}
void GoodixGT1151::reset() {
writeCommand(GT1151_CMD_RESET);
}
void GoodixGT1151::idle() {
writeCommand(GT1151_CMD_IDLE);
}
void GoodixGT1151::readTouchData(uint8_t* data) {
writeCommand(GT1151_CMD_READ_COORDS);
Wire.requestFrom(GT1151_I2C_ADDRESS, GT1151_TOUCH_DATA_SIZE);
for (int i = 0; i < GT1151_TOUCH_DATA_SIZE; i++) {
data[i] = Wire.read();
}
}
void GoodixGT1151::readCoords(TouchPoint* points) {
uint8_t data[GT1151_TOUCH_DATA_SIZE];
readTouchData(data);
// read the touch data for each touch point
for (int i = 0; i < GT1151_MAX_TOUCH_POINTS; i++) {
// calculate the starting index of the touch data for this touch point
int start = i * 5;
// read the touch coordinates and touch status for this touch point
points[i].x = (data[start + 3] << 8) | data[start + 2];
points[i].y = (data[start + 5] << 8) | data[start + 4];
points[i].touched = (data[start + 1] & 0x01) == 0x01;
}
}
void GoodixGT1151::writeCommand(uint8_t cmd) {
Wire.beginTransmission(GT1151_I2C_ADDRESS);
Wire.write(GT1151_REG_CMD >> 8);
Wire.write(GT1151_REG_CMD & 0xFF);
Wire.write(cmd);
Wire.endTransmission();
}
None of Waveshare's examples were made for Arduino and when I tried to replace their code with the wire library I couldn't get it to work. So instead I am using the code above which I feel like should work and is promising but the serial monitor just prints out -1 for the values. Currently I am testing the code on my Tinypico nano esp32 and have checked my wiring with a multimeter to confirm that everything is correct.
I have two guesses about my problem:
The waveshare library included code for a touch reset pin (TRST), which I am not using with my current code and am not sure how to do.
Or the GT1151 touchscreen driver is just broken and I should order a new display

Related

ESP32-C3 DevModule HSPI was not declared in this scope & no matching function for call to SPIClass Errors

I'm trying to get this Code for the AMT22 Encoder Using a ESP32C3-DevModule to work but the Arduino IDE is erroring me that "HSPI" is not declared in the scope any suggestions on what it should be declared as?
It also is Erroring for the line below
begin(_pinCLCK, _pinMISO, _pinMOSI, _pinSS);
but it should be pulling from the AMT22.h library those values.
#include "AMT22.h"
#include <stdlib.h>
#include <SPI.h>
SPIClass * AMT22::encoder = NULL; // this must be here -> see https://stackoverflow.com/questions/39336029/arduino-accessing-static-variable-in-the-classs-static-method
AMT22::AMT22(const byte CLCK,
const byte MISO,
const byte MOSI,
const byte SS) {
_pinCLCK = CLCK;
_pinMISO = MISO;
_pinMOSI = MOSI;
_pinSS = SS;
}
void AMT22::Begin() {
if (AMT22::encoder == NULL) {
AMT22::encoder = new SPIClass(HSPI);
AMT22::encoder -> setClockDivider(SPI_CLOCK_DIV32);
AMT22::encoder -> begin(_pinCLCK, _pinMISO, _pinMOSI, _pinSS); // SCLK, MISO, MOSI, SS
}
This is from the AMT22.h Library
private:
AMT22::Position getPositionSingle();
AMT22::Position getPositionMulti();
void setCSLine(uint8_t releaseLine);
uint8_t spiWriteRead(uint8_t sendByte, uint8_t releaseLine);
AMT22::Position position;
byte _pinMISO = 12;
byte _pinMOSI = 13;
byte _pinCLCK = 14;
byte _pinSS = 15;
// uninitalised pointers to SPI
objects
static SPIClass *encoder;
};
#endif
The code is intended to Get a Multiturn Function from the encoder- i.e. When the Motor spins the encoder will be able to serial print the amount of rotations counting upwards and downwards.

Can't handle nRF24L01+ using ESP32 (esp-idf)

I'm trying to port nRF24L01 library to ESP32 (I'm using esp-idf). All I have to do is to replace functions that are using spi. That's how I do this:
static uint8_t *create_tx(uint8_t cmd, const uint8_t *buff, uint8_t length){
uint8_t *tx = (uint8_t*)heap_caps_malloc(64, MALLOC_CAP_DMA);
tx[0] = cmd;
if(buff != NULL)
memcpy(tx + 1, buff, length);
return tx;
}
uint8_t NRF24L01::Read(uint8_t cmd, uint8_t *pBuff, uint8_t length){
uint8_t *recv = (uint8_t*)heap_caps_malloc(64, MALLOC_CAP_DMA);
uint8_t *send = (uint8_t*)heap_caps_malloc(64, MALLOC_CAP_DMA);
memset(send, NRF24_CMD_NOP, 32);
send[0] = cmd;
CSPIBuilder builder;
spi_transaction_t t =
builder
.SetLength(length)
.SetTx(send)
.SetRx(recv)
.build();
spi_device_transmit(m_Spi, &t);
memcpy(pBuff, recv + 1, length);
uint8_t status = recv[0];
free(recv);
free(send);
return status;
}
uint8_t NRF24L01::Write(uint8_t cmd, uint8_t *pBuff, uint8_t length){
uint8_t *txBuff = create_tx(cmd, pBuff, length);
uint8_t *rxBuff = (uint8_t*)heap_caps_malloc(64, MALLOC_CAP_DMA);
memset(rxBuff, NRF24_CMD_NOP, length + 1);
spi_transaction_t t =
CSPIBuilder()
.SetLength(length)
.SetTx(txBuff)
.SetRx(rxBuff)
.build();
spi_device_transmit(m_Spi, &t);
free(txBuff);
uint8_t status = rxBuff[0];
free(rxBuff);
return status;
}
class CSPIBuilder{
public:
CSPIBuilder(){
memset(&t, 0, sizeof(t));
}
CSPIBuilder &UseTxData() { t.flags |= SPI_TRANS_USE_TXDATA; return *this; }
CSPIBuilder &UseRxData() { t.flags |= SPI_TRANS_USE_RXDATA; return *this; }
CSPIBuilder &UseTRxData() { t.flags |= SPI_TRANS_USE_TXDATA | SPI_TRANS_USE_RXDATA; return *this; }
CSPIBuilder &SetLength(uint8_t length) { t.length = (length + 1) * 8; return *this; }
CSPIBuilder &SetRxLength(uint8_t rxLength) { t.rxlength = (rxLength + 1) * 8; return *this; }
CSPIBuilder &SetTx(uint8_t *txBuffer) { t.tx_buffer = txBuffer; return *this; }
CSPIBuilder &SetRx(uint8_t *rxBuffer) { t.rx_buffer = rxBuffer; return *this; }
spi_transaction_t build() {return t;}
private:
spi_transaction_t t;
};
But... There is nothing works. SPI wires are connected properly. I can read status via spi. I cannot confirm that it is correct value, but it's changing every time I distonnect GND from nRF24L01. So I think wiring is OK.
What's wrong with this code?
Well, as I understood there are big problems with native esp-idf spi api. The solution was to replace full spi transaction (more than 1 byte) by small transactions byte-by-byte (since spi api can send only first byte correctly (in my case atleast)). Also I have to control CS pin by myself and respect datasheet's timings
The result of these manipulations is my own library (haha)
Feel free to use it

Trying to send a float value over SPI between 2 Arduinos

I am currently trying to send a float value across two Arduinos via SPI. Currently I am working to send a static value of 2.25 across and then read it via the Serial.println() command. I would then want to pass a float value from a linear displacement sensor. My end goal is to be able to have the master ask for information, the slave gathers the appropriate data and packages it and then master receives said data and does what it needs with it.
Currently I am getting an error "call of overloaded 'println(byte [7])' is ambiguous" and I am not to sure why I am getting this error. I am currently a mechanical engineering student and I am crash-coursing myself through C/C++. I am not entirely positive about what I am doing. I know that a float is 4 bytes and I am attempting to create a buffer of 7 bytes to store the float and the '\n' char with room to spare. My current code is below.
Master:
#include <SPI.h>
void setup() {
pinMode(SS,OUTPUT);
digitalWrite(SS,HIGH);
SPI.begin();
SPI.setClockDivider(SPI_CLOCK_DIV4);
}
void loop() {
digitalWrite(SS,LOW);
float a = 2.25;
SPI.transfer(a);
SPI.transfer('\n');
digitalWrite(SS,HIGH);
}
My slave code is as follows:
#include <SPI.h>
byte buf[7];
volatile byte pos = 0;
volatile boolean process_it = false;
void setup() {
Serial.begin(9600);
pinMode(MISO,OUTPUT);
digitalWrite(MISO,LOW);
SPCR |= _BV(SPE); // SPI Enable, sets this Arduino to Slave
SPCR |= _BV(SPIE); // SPI interrupt enabled
}
ISR(SPI_STC_vect) {
// Interrupt Service Routine(SPI_(SPI Transfer Complete)_vector)
byte c = SPDR;
// SPDR = SPI Data Register, so you are saving the byte of information in that register to byte c
if (pos < sizeof buf) {
buf[pos++] = c;
if (c == '\n') {
process_it = true;
}
}
}
void loop() {
if (process_it = true) {
Serial.println(buf);
pos = 0;
process_it = false;
}
}
I figured out what I needed to do and I wanted to post my finished code. I also added an ability to transfer more than one float value.
Master:
#include <SPI.h>
float a = 3.14;
float b = 2.25;
uint8_t storage [12];
float buff[2] = {a, b};
void setup()
{
digitalWrite(SS, HIGH);
SPI.begin();
Serial.begin(9600);
SPI.setClockDivider(SPI_CLOCK_DIV8);
}
void loop()
{
digitalWrite(SS, LOW);
memcpy(storage, &buff, 8);
Serial.print("storage[0] = "); Serial.println(storage[0]); // the
following serial prints were to check i was getting the right decimal
numbers for the floats.
Serial.print("storage[1] = "); Serial.println(storage[1]);
Serial.print("storage[2] = "); Serial.println(storage[2]);
Serial.print("storage[3] = "); Serial.println(storage[3]);
Serial.print("storage[4] = "); Serial.println(storage[4]);
Serial.print("storage[5] = "); Serial.println(storage[5]);
Serial.print("storage[6] = "); Serial.println(storage[6]);
Serial.print("storage[7] = "); Serial.println(storage[7]);
SPI.transfer(storage, sizeof storage ); //SPI library allows a user to
transfer a whole array of bytes and you need to include the size of the
array.
digitalWrite(SS, HIGH);
delay(1000);
}
For my Slave code:
#include <SPI.h>
byte storage [8];
volatile byte pos;
volatile boolean process;
float buff[2];
void setup()
{
pinMode(MISO,OUTPUT);
SPCR |= _BV(SPE);
SPCR |= _BV(SPIE);
pos = 0;
process = false;
Serial.begin(9600);
}
ISR(SPI_STC_vect)
{
byte gathered = SPDR;
if( pos < sizeof storage)
{
storage[pos++] = gathered;
}
else
process = true;
}
void loop()
{
if( process )
{
Serial.print("storage[0] = "); Serial.println(storage[0]);
Serial.print("storage[1] = "); Serial.println(storage[1]);
Serial.print("storage[2] = "); Serial.println(storage[2]);
Serial.print("storage[3] = "); Serial.println(storage[3]);
Serial.print("storage[4] = "); Serial.println(storage[4]);
Serial.print("storage[5] = "); Serial.println(storage[5]);
Serial.print("storage[6] = "); Serial.println(storage[6]);
Serial.print("storage[7] = "); Serial.println(storage[7]);
memcpy(buff,&storage,8);
Serial.print("This is buff[0]");Serial.println(buff[0]);
Serial.print("This is buff[1]");Serial.println(buff[1]);
storage[pos] = 0;
pos = 0;
process = false;
}
}
The immediate problem is that Serial.print doesn't know what to do with a byte array. Either declare it as a char array or cast it in the print statement:
char buf[7];
OR
Serial.print((char*) buf);
Either way, though, it's not going to show up as a float like you want.
An easier way to do all this is to use memcpy or a union to go back and forth between float and bytes. On the master end:
uint8_t buf[4];
memcpy(buf, &a, 4);
Then use SPI to send 4 bytes. Reverse it on the peripheral end.
Note that sending '\n' as the termination byte is a bad idea because it can lead to weird behavior, since one of the bytes in the float could easily be 0x0a, the hexadecimal equivalent of '\n'.

SoftwareSerial.h not found on Sodaq Arduino

I have an arduino sodaq with a MIcrochip LoRabee attached, as well as a GPS module. I am trying to use SoftwareSerial to read the GPS data but it won't recognise it!
The sketch was previously working on a Chinese cloned Nano and I was able to read the data fine. I've changed the ports to 4 and 5 (I was using 3 and 4 on the Chinese Nano) but other than that the code is identical.
Any ideas?
#include <TinyGPS++.h>
#include <SoftwareSerial.h>
/*
This sample code demonstrates the normal use of a TinyGPS++ (TinyGPSPlus) object.
It requires the use of SoftwareSerial, and assumes that you have a
4800-baud serial GPS device hooked up on pins 4(rx) and 3(tx).
*/
static const int RXPin = 2, TXPin = 3;
static const uint32_t GPSBaud = 9600;
// The TinyGPS++ object
TinyGPSPlus gps;
// The serial connection to the GPS device
SoftwareSerial ss(RXPin, TXPin);
void setup()
{
Serial.begin(115200);
ss.begin(GPSBaud);
Serial.println(F("FullExample.ino"));
Serial.println(F("An extensive example of many interesting TinyGPS++ features"));
Serial.print(F("Testing TinyGPS++ library v. ")); Serial.println(TinyGPSPlus::libraryVersion());
Serial.println(F("by Mikal Hart"));
Serial.println();
Serial.println(F("Sats HDOP Latitude Longitude Fix Date Time Date Alt Course Speed Card Distance Course Card Chars Sentences Checksum"));
Serial.println(F(" (deg) (deg) Age Age (m) --- from GPS ---- ---- to London ---- RX RX Fail"));
Serial.println(F("---------------------------------------------------------------------------------------------------------------------------------------"));
}
void loop()
{
static const double LONDON_LAT = 51.508131, LONDON_LON = -0.128002;
printInt(gps.satellites.value(), gps.satellites.isValid(), 5);
printInt(gps.hdop.value(), gps.hdop.isValid(), 5);
printFloat(gps.location.lat(), gps.location.isValid(), 11, 6);
printFloat(gps.location.lng(), gps.location.isValid(), 12, 6);
printInt(gps.location.age(), gps.location.isValid(), 5);
printDateTime(gps.date, gps.time);
printFloat(gps.altitude.meters(), gps.altitude.isValid(), 7, 2);
printFloat(gps.course.deg(), gps.course.isValid(), 7, 2);
printFloat(gps.speed.kmph(), gps.speed.isValid(), 6, 2);
printStr(gps.course.isValid() ? TinyGPSPlus::cardinal(gps.course.value()) : "*** ", 6);
unsigned long distanceKmToLondon =
(unsigned long)TinyGPSPlus::distanceBetween(
gps.location.lat(),
gps.location.lng(),
LONDON_LAT,
LONDON_LON) / 1000;
printInt(distanceKmToLondon, gps.location.isValid(), 9);
double courseToLondon =
TinyGPSPlus::courseTo(
gps.location.lat(),
gps.location.lng(),
LONDON_LAT,
LONDON_LON);
printFloat(courseToLondon, gps.location.isValid(), 7, 2);
const char *cardinalToLondon = TinyGPSPlus::cardinal(courseToLondon);
printStr(gps.location.isValid() ? cardinalToLondon : "*** ", 6);
printInt(gps.charsProcessed(), true, 6);
printInt(gps.sentencesWithFix(), true, 10);
printInt(gps.failedChecksum(), true, 9);
Serial.println();
smartDelay(1000);
if (millis() > 5000 && gps.charsProcessed() < 10)
Serial.println(F("No GPS data received: check wiring"));
}
// This custom version of delay() ensures that the gps object
// is being "fed".
static void smartDelay(unsigned long ms)
{
unsigned long start = millis();
do
{
while (ss.available())
gps.encode(ss.read());
} while (millis() - start < ms);
}
static void printFloat(float val, bool valid, int len, int prec)
{
if (!valid)
{
while (len-- > 1)
Serial.print('*');
Serial.print(' ');
}
else
{
Serial.print(val, prec);
int vi = abs((int)val);
int flen = prec + (val < 0.0 ? 2 : 1); // . and -
flen += vi >= 1000 ? 4 : vi >= 100 ? 3 : vi >= 10 ? 2 : 1;
for (int i=flen; i<len; ++i)
Serial.print(' ');
}
smartDelay(0);
}
static void printInt(unsigned long val, bool valid, int len)
{
char sz[32] = "*****************";
if (valid)
sprintf(sz, "%ld", val);
sz[len] = 0;
for (int i=strlen(sz); i<len; ++i)
sz[i] = ' ';
if (len > 0)
sz[len-1] = ' ';
Serial.print(sz);
smartDelay(0);
}
static void printDateTime(TinyGPSDate &d, TinyGPSTime &t)
{
if (!d.isValid())
{
Serial.print(F("********** "));
}
else
{
char sz[32];
sprintf(sz, "%02d/%02d/%02d ", d.month(), d.day(), d.year());
Serial.print(sz);
}
if (!t.isValid())
{
Serial.print(F("******** "));
}
else
{
char sz[32];
sprintf(sz, "%02d:%02d:%02d ", t.hour(), t.minute(), t.second());
Serial.print(sz);
}
printInt(d.age(), d.isValid(), 5);
smartDelay(0);
}
static void printStr(const char *str, int len)
{
int slen = strlen(str);
for (int i=0; i<len; ++i)
Serial.print(i<slen ? str[i] : ' ');
smartDelay(0);
}
Sodaq wrote their own softwareserial library. If you install that library, it should resolve your issues:
You can find it here.
But it doesn't work. I tried it.
But u can use this.
Hardware Serials
The SODAQ ONE has 3 hardware serials:
SerialUSB – This is for when you are debugging over the USB Cable.
Serial – Serial is attached to pin D12/A12/TX and D13/A12/RX.
Serial1 – Is connected to the RN2483 LoRaWAN Module.
Serial is connected to pin 12 and 13
SerialUSB is for debugging over the usb cable
Instead of SoftwareSerial ss(RXPin, TXPin); you could add:
#define ss Serial
All your code with Serial must be SerialUSB
And then something else. Are u still using a gps module or is this a gns? If so you can try neogps. Here is an example for the sodaq explorer.
https://github.com/Kaasfabriek/Junior_Internet_of_Things_2018/blob/master/test_NMEAloc/test_NMEAloc.ino
For the sodaq explorer u might need a hack if u will use neogps like this.
https://github.com/Kaasfabriek/Junior_Internet_of_Things_2018/tree/master/hack
Neogps can be found here. I see u are using tinygps, if u have a gps that talks gps dialect that will work. If u have a gns it won't.
https://github.com/SlashDevin/NeoGPS

I2C between RPI and Arduino using Processing

Posted here is my code for my RPi master and Arduino slave project. I have an analog sensor connected to the Arduino and i am reading this data with Processing on the RPi. I am using Processing because I intend on generating a graph and waveform with the data. The code below seems to work, however, any slight movement of setup "disconnects" the slave device because I get the following message. "The device did not respond. Check the cabling and whether you are using the correct address." I have narrowed the problem down and found out that it always disconnects at the i2c.read();function. My question is whether there is some type of break function so that when this does happen processing moves on and tries again in the next iteration? Or if it is stuck in a loop is it waiting for some signal from the slave device? Does anyone have any suggestions on how to approach this?
Processing Code
import processing.io.*;
I2C i2c;
int val = 0;
void setup()
{
i2c = new I2C(I2C.list()[0]);
}
void draw ()
{
if (I2C.list() != null)
{
i2c.beginTransmission(0x04);
i2c.write(8);
byte[] in = i2c.read(1);
int accel = in[0];
println (accel);
}
}
Arduino Code
#include <Wire.h>
#define SLAVE_ADDRESS 0x04
int number = 5;
int state = 0;
const int zInput = A0;
int zRawMin = 493;
int zRawMax = 530;
float acceleration;
int accel;
void setup() {
analogReference(EXTERNAL);
pinMode(13,OUTPUT);
Serial.begin(9600); // start serial for output
Wire.begin(SLAVE_ADDRESS); // join i2c bus with address #8
Wire.onReceive(receiveData); // register event
Wire.onRequest(sendData);
Serial.println ("Ready");
}
void loop() {
int zRaw = ReadAxis (zInput);
acceleration = map (float(zRaw), float (zRawMin), float(zRawMax), -9.81, 9.81);
accel = int(acceleration);
//delay(100);
}
void receiveData(int byteCount)
{
while (0 < Wire.available())
{ // loop through all but the last
number = Wire.read(); // receive byte as a character
//Serial.print("data received");
Serial.println(number); // print the character
if (number==1)
{
if (state == 0)
{
digitalWrite(13,HIGH);
state = 1;
}
else
{
digitalWrite(13,LOW);
state = 0;
}
}
}
}
void sendData()
{
Wire.write(accel);
}
int ReadAxis(int axisPin)
{
long reading = 0;
int raw = analogRead(axisPin);
return raw;
}
Looks like a solution might be to use a try/catch block courtesy of #Kevin Workman. It works well for what I need it to do thx.
here is the updated Processing code.
import processing.io.*;
I2C i2c;
int val = 0;
void setup()
{
i2c = new I2C(I2C.list()[0]);
}
void draw ()
{
if (I2C.list() != null)
{
i2c.beginTransmission(0x04);
i2c.write(8);
try
{
byte[] in = i2c.read(1);
}
catch(Exception e)
{
i2c.endTransmission();
}
int accel = in[0];
println (accel);
}
}

Resources