I have an Adafruit Sharp Memory display connected via SPI to Arduino Nano Connect RP2040. I don't use Arduino IDE nor libraries. I write the code in C++ like I would write for RP2040 on Pi Pico, so I'm using Pico/RP2040 libraries. I'm building it and then just copying the .uf2 file to Arduino.
I'm trying to control the display but without success and I have no idea what I'm doing wrong. Here is my code, where I'm sending a command which should clear the display but it does not:
#include <stdio.h>
#include <stdlib.h>
#include "pico/stdlib.h"
#include "hardware/spi.h"
#include "hardware/gpio.h"
// ---SPI
// Pins for Arduino
#define SCK_PIN 13 // SCLK / SCK
#define MOSI_PIN 11 // MOSI / COPI
#define SS_PIN 10 // SS / CS
// ---Sharp display
#define WIDTH 144
#define HEIGHT 168
int main() {
stdio_init_all();
printf("START \n");
bool vcom_bool_{false};
spi_init(spi0, 2000000);
spi_set_format( spi0, 8, SPI_CPOL_0, SPI_CPHA_0, SPI_MSB_FIRST);
gpio_set_function(MOSI_PIN, GPIO_FUNC_SPI);
gpio_set_function(SCK_PIN, GPIO_FUNC_SPI);
gpio_init(SS_PIN);
gpio_set_dir(SS_PIN, GPIO_OUT);
gpio_put(SS_PIN, 0); // this display is low on inactive
while(true)
{
printf("VCOM = %b \n", vcom_bool_);
gpio_put(SS_PIN, 1);
// Clear the display
uint8_t buf[2];
if(vcom_bool_)
{
buf[0] = 0b01100000;
vcom_bool_ = false;
}
else
{
buf[0] = 0b00100000;
vcom_bool_ = true;
}
buf[1] = 0b00000000;
spi_write_blocking(spi0, buf, 2);
gpio_put(SS_PIN, 0);
sleep_ms(10);
sleep_ms(500);
}
}
Display and wiring are ok, because when I run example code from Adafruit (it is using Arduino's libraries) it works.
I follow this documentation from Sharp: https://www.sharpsde.com/fileadmin/products/Displays/2016_SDE_App_Note_for_Memory_LCD_programming_V1.3.pdf
I also reviewed the code from Adafruit and the SPI communication seems to be done in the same way.
What am I doing wrong?
Is there some issue with using Pico libraries for Arduino Nano RP2040? I did I2C communication in the same way (Pico/RP2040 libraries, .uf2 copied to Arduino Nano RP2040) and it worked.
Related
I am getting started with GPS modules, for my project I am using the NEO 6M GPS module with a Ceramic Antenna.
So, earlier I tried to connect the GPS module with an Arduino Nano and was able to successfully display the GPS NEMA sentences output on the Arduino IDE Serial Monitor, although the GPS module was not able to connect to any satellites.
Now, I am trying to add an SSD1306 OLED module to this project. So, that the latitude and the longitude values can be fetched from the GPS module and can be displayed on the OLED Screen whenever the GPS updates its position.
The code which I have written so far was compiled properly in the Arduino IDE, but the OLED module failed to display the expected information.
I kept on getting the "SSD1306 allocation failed" error on the Serial Monitor.
I have already verified the I2C Address for my OLED display module which is 0x3C instead of 0x3D.
I have also tested the OLED display with a separate code and it is working fine.
Then also I am not able to figure out what's wrong with this code that it is leading to these unexpected results.
The code which I am using for this project is attached below.
So, if a fellow programmer from the community can help me solve this issue then that would be really appreciated.
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <TinyGPS++.h>
#include <SoftwareSerial.h>
#define OLED_WIDTH 128
#define OLED_HEIGHT 64
#define OLED_RESET -1
#define OLED_ADDR 0x3C
Adafruit_SSD1306 oled(OLED_WIDTH, OLED_HEIGHT, &Wire, OLED_RESET);
SoftwareSerial serial_connect(4, 3); //Rx:pin(4) Tx:pin(3)
TinyGPSPlus gps;
void setup()
{
Serial.begin(9600);
serial_connect.begin(9600);
// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
if(!oled.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR))
{
Serial.println(F("SSD1306 allocation failed"));
for(;;); // Don't proceed, loop forever
}
Serial.println("GPS start");
oled.clearDisplay();
oled.setTextSize(1);
oled.setTextColor(SSD1306_WHITE);
oled.setCursor(0, 0);
oled.print("Detecting GPS");
oled.setCursor(0, 10);
oled.print("Coordinates");
oled.display();
delay(5000); //5 seconds delay
}
void loop()
{
while(serial_connect.available())
{
gps.encode(serial_connect.read());
}
if(gps.location.isUpdated())
{
Serial.println("Satellite Count:");
Serial.println(gps.satellites.value());
Serial.println("Latitude:");
Serial.println(gps.location.lat(),6);
Serial.println("Longitude:");
Serial.println(gps.location.lng(),6);
Serial.println("Speed MPH:");
Serial.println(gps.speed.mph());
Serial.println("Altitude Feet:");
Serial.println(gps.altitude.feet());
Serial.println(" ");
oled.clearDisplay();
oled.setCursor(0, 0);
oled.print("Lati=");
oled.setCursor(0, 10);
oled.print(gps.location.lat(),6);
oled.setCursor(10, 0);
oled.print("Long=");
oled.setCursor(10, 10);
oled.print(gps.location.lng(),6);
oled.display();
delay(500);
}
}
It's a bit late now, but letsee... That's an interesting issue.
Your code follows the examples provided by Adafruit, w.r.t. SSD1306. When you define pins 3 and 4 for the GPS's UART, which pins are you using? D3 and D4? Which pins are you using for the I2C OLED display? You have to make sure that your OLED display has the SDA and the SCL connected to A4 and A5, respectively.
Have you done anything different when the display worked, e.g. use a different platform or MCU?
I'm pretty new to programming in C, but getting used to registers and the way communication in C works. Since UART using the official Arduino read() / write() creates a high delay in passing commands through, I tried to translate this Arduino sketch into pure C. (and because I've time to play around, haha)
My ebike's controller and display are communicating using UART. I tried to read the commands and react to speed changes or brake signals, but first of all I need to get rid of this huge delay in updating the display.
I'm using an Robodyn Mega 2560 PRO (Embed), which has 4x hardware serial ports. In the first step I tried to read what's coming in and forward it to the other port. Shouldn't be to hard to implement in C, right?
void setup() {
Serial1.begin(1200); // BBSHD controller #RX18 TX19
Serial2.begin(1200); // Display DP-C18 #TX16 RX17
}
void loop() {
if (Serial2.available()) {
Serial1.write(Serial2.read());
}
if (Serial1.available()) {
Serial2.write(Serial1.read());
}
}
That's what I programmed in Atmel Studio 7 so far. I used the C example from ATmega640/1280/1281/2560/2561 - Complete Datasheet (Search for USART_Receive and USART_Transmit) and this guide Simple Serial Communications With AVR libc
Currently I can compile and flash it the 2560, but the communication is not being forwarded. I don't know what the default settings are, that Arduino with Serial uses. Which mode, number of stop bits, .. Is there anything obvious I'm missing?
#define F_CPU 16000000UL
#define BAUD 1200
#include <avr/io.h>
#include <stdio.h>
#include <util/setbaud.h>
void uart_init(void) {
/* Serial1 controller */
UBRR1H = UBRRH_VALUE;
UBRR1L = UBRRL_VALUE;
/* Serial2 display */
UBRR2H = UBRRH_VALUE;
UBRR2L = UBRRL_VALUE;
/* 8-bit data, 1stop bit*/
UCSR1C = (1<<UCSZ11) | (1<<UCSZ10);
UCSR2C = (1<<UCSZ21) | (1<<UCSZ20);
/* Enable RX and TX */
UCSR1B = (1<<RXEN1) | (1<<TXEN1);
UCSR2B = (1<<RXEN2) | (1<<TXEN2);
}
int main(void) {
uart_init();
while(1) {
if (!(UCSR1A & (1<<RXC1))) { /* Only if data is received */
while (!(UCSR1A & (1<<UDRE1))); /* Wait for empty transmit buffer */
UDR2 = UDR1; /* Put data into buffer, sends the data */
}
if (!(UCSR2A & (1<<RXC2))) { /* Only if data is received */
while (!(UCSR2A & (1<<UDRE2))); /* Wait for empty transmit buffer */
UDR1 = UDR2; /* Put data into buffer, sends the data */
}
}
}
I want to control LED diod with PWM using bcm2835.h and pure C langueage. My code does not work. What am I missing?
I have tried "gpio" console command and it works fine, so I know that led is connected to the right ports. I can turn it on using console command:
gpio pwm 1 1024
My code:
#include <bcm2835.h>
#include <stdio.h>
// PWM output on RPi Plug P1 pin 12 (which is GPIO pin 18) in alt fun 5.
// Note that this is the _only_ PWM pin available on the RPi IO headers
#define PIN RPI_GPIO_P1_12
// and it is controlled by PWM channel 0
#define PWM_CHANNEL 0
// This controls the max range of the PWM signal
#define RANGE 1024
int main(int argc, char **argv)
{
if (!bcm2835_init())
{
return 1;
}
// Set the output pin to Alt Fun 5, to allow PWM channel 0 to be output there
bcm2835_gpio_fsel(PIN, BCM2835_GPIO_FSEL_ALT5);
// Clock divider is set to 16.
// With a divider of 16 and a RANGE of 1024, in MARKSPACE mode,
// the pulse repetition frequency will be
// 1.2MHz/1024 = 1171.875Hz, suitable for driving a DC motor with PWM
bcm2835_pwm_set_clock(BCM2835_PWM_CLOCK_DIVIDER_16);
bcm2835_pwm_set_mode(PWM_CHANNEL, 1, 1);
bcm2835_pwm_set_range(PWM_CHANNEL, RANGE);
while(1)
{
bcm2835_pwm_set_data(PWM_CHANNEL, 1024);
bcm2835_delay(10);
}
bcm2835_close();
return 0;
}
I expect that my LED will turn on.
This is stupid, but after checking the math, code, wiring I discovered that app needs to be run with root privileges to have on-board access to the pins. It works fine. Topic can be closed.
I'm trying to read the on board temp sensor of the msp430fr5739 micro controller and display the results in a terminal.
using C the task should be accomplished!!!
All the code and custom libraries can be found on GitHub
My operating system is ubuntu and the IDE I'm using is code composer studio
here is the main.c
#include <msp430fr5739.h>
#include "system.h"
#include "temp.h"
#include "uart.h"
/*
main.c
1. Switches and LEDs
2.
3. Temp sens
*/
int main(void) {
WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer
unsigned int tempVal = 0; // temp readings
LEDs_INIT(); // Init leds
SWITCHEs_INIT(); // Init Switches
serialBegin(); // Begin Serial communication at 9600 buad
while (1)
{
__bis_SR_register(LPM4_bits + GIE); // Enter LPM4 with interrupts enabled
tempVal = getThermisterVal();
}
return 0;
}
I've tried to follow the demo code that TI had shipped with the board and the resulting libs are published on GitHub (I didn't post all the lib and code, simply because it's too long)
Now I'm really struggling with the serial communication part, i know that the bytes sent from the micro-controller has to be read by some sort of serial monitor application on PC.
Any help is appreciated.
I'm currently trying to interface my Tiva C Series with a Sparkfun Breakout Board, IMU Digital Combo Board - 6 Degrees of Freedom ITG3200/ADXL345 and I'm having trouble with the I2C interface.
currently this is my code:
#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/sysctl.h"
#include "driverlib/gpio.h"
#include "driverlib/i2c.h"
uint8_t SLAVE_ADDRESS = 0x68;
uint32_t first_byte, second_byte, temperature, result;
void i2c_setup(void) {
//Enable the I2C Module
SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C2);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
//Wait at least 5 clock cycles
SysCtlDelay(2);
//Configure SDA and SCL
GPIOPinConfigure(GPIO_PE4_I2C2SCL);
GPIOPinConfigure(GPIO_PE5_I2C2SDA);
//Wait at least 5 clock cycles
SysCtlDelay(2);
//Set PE4 as SCL
GPIOPinTypeI2CSCL(GPIO_PORTE_BASE, GPIO_PIN_4);
//Set PE5 as SDA
GPIOPinTypeI2C(GPIO_PORTE_BASE, GPIO_PIN_5);
//Configure Master,
I2CMasterInitExpClk(I2C2_BASE, SysCtlClockGet(), false);
}
uint32_t i2c_read() {
I2CMasterSlaveAddrSet(I2C2_BASE, SLAVE_ADDRESS, false);
I2CMasterDataPut(I2C2_BASE, 0x1A);
I2CMasterControl(I2C2_BASE, I2C_MASTER_CMD_SINGLE_SEND);
while(I2CMasterBusBusy(I2C2_BASE)); //Loop until the bus is no longer busy
I2CMasterSlaveAddrSet(I2C2_BASE, SLAVE_ADDRESS, true );
I2CMasterControl(I2C2_BASE, I2C_MASTER_CMD_SINGLE_RECEIVE);
while(I2CMasterBusBusy(I2C2_BASE)); //Loop until the bus is no longer busy
first_byte = I2CMasterDataGet(I2C2_BASE);
return first_byte;
}
void setup()
{
Serial.begin(9600);
i2c_setup();
}
void loop()
{
int test = i2c_read();
Serial.println(test);
delay(1000);
}
I'm using Energia to test my program, and when I try to read from the specified register, I get the same result, no matter which register I choose, the result is always decimal 229 (this is the Accelerometer's Device Address).
Can somebody point me in the right direction, I've been looking at my code for quite some time and still don't know whats wrong...
Thanks!
I skimmed through your code and everything seems Okay. Clearly something is working right if you get a response. But Like Martin said , figuring the problem without being there is somewhat difficult. Instead of Writing 0x1A can you try using one of the other I2C commands for the accelerametor ? Also if the jumper is connected to VDD your address should be 0x69 (105 decimal) are you sure it's 0x68 ?
I looked up the documentation on sparkfuns website and they provided the following list
of commands.
char WHO_AM_I = 0x00;
char SMPLRT_DIV= 0x15;
char DLPF_FS = 0x16;
char GYRO_XOUT_H = 0x1D;
char GYRO_XOUT_L = 0x1E;
char GYRO_YOUT_H = 0x1F;
char GYRO_YOUT_L = 0x20;
char GYRO_ZOUT_H = 0x21;
char GYRO_ZOUT_L = 0x22;
GL hope everything works out. Been meaning to buy my own to play around with so keep me posted !