is there a way to modify SparkFun_MS5803_I2C .cpp /.h to allow user defined (non-default) I2C SDA/SCL pins for use with TwoWire? - i2c

I am using a ESP32-SIM800L with GPRS / MS5803-14BA / BME280 / SH1106 OLED
The modem and sensor setup (using TwoWire ) is as follows (relevant extracts only):
#include <Wire.h>
...
#define I2C_SDA 21
#define I2C_SCL 22
#define I2C_SDA_2 18
#define I2C_SCL_2 19
...
#include <SparkFun_MS5803_I2C.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#include "SH1106Wire.h"
TwoWire I2CPower = TwoWire(0);
TwoWire I2CMS = TwoWire(1); // I2C bus for MS5803 # 0x77
TwoWire I2CBME = TwoWire(1); // I2C bus for BME280 # 0x76
TwoWire I2CSH = TwoWire(1); // I2C bus for SH1106 OLED # 0x3c
MS5803 sensor(ADDRESS_LOW); // default is ADDRESS_HIGH = 0x76 // ADDRESS_LOW = 0x77
Adafruit_BME280 bme;
SH1106Wire display(0x3c, I2C_SDA_2, I2C_SCL_2);
...
void setup() {
...
I2CPower.begin(I2C_SDA, I2C_SCL, 400000); // start I2C bus No. 1 for SIM800L
I2CMS.begin(I2C_SDA_2, I2C_SCL_2, 400000); // start I2C bus No. 2 for MS5803
I2CBME.begin(I2C_SDA_2, I2C_SCL_2, 400000); // start I2C bus No. 2 for BME280
I2CSH.begin(I2C_SDA_2, I2C_SCL_2, 400000); // start I2C bus No. 2 for SH1106 OLED
...
// Init BME280 # 0x76
if (!bme.begin(0x76, &I2CBME)) {
Serial.println("No valid BME280 sensor # 0x76, check wiring!");
} else {
Serial.println("BME280 # 0x76 : Ok");
}
// Init MS5803 # 0x77
sensor.reset();
delay(500);
//sensor.begin();
//delay(500);
if (!sensor.begin()) {
Serial.println("No valid MS5803 sensor # 0x77");
} else {
Serial.println("MS5803 # 0x77 : Ok");
}
// Init SH1106 OLED # 0x3c
display.init();
Serial.println("SH1106 OLED # 0x3c : SCREEN CHECK");
display.flipScreenVertically();
display.setFont(ArialMT_Plain_16);
display.setTextAlignment(TEXT_ALIGN_LEFT);
display.drawString(0,0,"SCREEN ON");
display.display();
...
} // End void setup()
void loop() {
read sensors and report & etc. ...
}
The Modem, BME280 and SH1106 OLED are all found and work, however the MS5803 is not picked up.
There are no I2C address clashes (0x76,0x33,0x77 respectivly).
Object creation or initialization of the BME280 and SH1106 OL allow explicit SDA/SCL pin assignments:
SH1106Wire display(0x3c, I2C_SDA_2, I2C_SCL_2);
...
bme.begin(0x76, &I2CBME)
however creation of the MS5803 object and its initialization has no provision for this:
MS5803 sensor(ADDRESS_LOW);
...
sensor.begin();
Trying to enter explicit pin numbers or reference to its TwoWire object in these expressions produces an error warning that there is no such function to allow such assignment.
Basically, if the modem, the BME280 and SH1106 OLED are not used, and TwoWire is not needed or invoked, then the MS5803 runs perfectly without pin assignment using the default I2C Pins (which for my ESP32Sim800L are 21/22). It is the issue of trying to put the sensor on a second I2C wire that seems problematic.
Can anyone explain how to use the MS5803 with TwoWire? Having looked on GitHub at the Sparkfun .h & .cpp I cant see one or how to explicitly set the SDA/SCL pins. Is there a way. Any pointers much appreciated.

Related

Unable to use PC15 as GPIO input on stm32f030rc

I'm working on a project using an stm32f030rc. I need to use PC15 as a GPIO input but it appears I'm unable to.
I understand the couple PC14/PC15 is shared with the LFE oscillator, but of course I'm not using that function. Moreover, I am able to read the correct pin level on the PC14 GPIO. In the datasheed regarding my model the PC15 pin is marked as a I/O with OSC32_OUT as additional function: can it be used as input at all?
For reference, this is the C code I'm using to test the functionality; I'm using libopencm3 for initialization.
#include <libopencm3/stm32/rcc.h>
#include <libopencm3/stm32/gpio.h>
static void clock_setup(void)
{
rcc_clock_setup_in_hsi_out_48mhz();
/* Enable GPIOA, GPIOB, GPIOC clock. */
rcc_periph_clock_enable(RCC_GPIOA);
rcc_periph_clock_enable(RCC_GPIOB);
rcc_periph_clock_enable(RCC_GPIOC);
rcc_periph_clock_enable(RCC_DBGMCU);
/* Enable clocks for GPIO port B and C*/
gpio_mode_setup(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO5);
gpio_mode_setup(GPIOC, GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO15);
gpio_mode_setup(GPIOC, GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO14);
}
int main(void)
{
unsigned long long i = 0;
clock_setup();
/* Blink the LED (PA8) on the board with every transmitted byte. */
while (1)
{
gpio_toggle(GPIOA, GPIO5); /* LED on/off */
for (i = 0; i < 400000; i++) /* Wait a bit. */
__asm__("nop");
// This conditional is never entered
if (gpio_get(GPIOC, GPIO15) == 0) {
__asm__("nop");
__asm__("nop");
__asm__("nop");
}
// This one works
if (gpio_get(GPIOC, GPIO14) == 0) {
__asm__("nop");
__asm__("nop");
__asm__("nop");
}
}
return 0;
}
PC14 & PC15 have the same configuration properties. Of course, there are some limitations regarding using these pins as outputs (including PC13), but it should be okay to use them as inputs as long as you don't activate LSE functionality.
PC14 & PC15 are GPIO inputs after power-up and considering that LSE is disabled by default, you should be able to use them directly even without any configuration.
As you don't have any problems with PC14, I suspect 3 possible causes:
1) A bug in the GPIO code the library provides. Although it's very unlikely, it's easy to test. You can remove the configuration code for PC14 & PC15, as they are GPIO inputs after power-up by default. This eliminates the possibility of having a bug in gpio_mode_setup() function. To avoid using gpio_get() function, you can use the following code:
if (GPIOC->IDR & (1 << 15) == 0)
2) A bug in the clock config code the library provides. Again, this one is very unlikely, but you can test it by removing the rcc_clock_setup_in_hsi_out_48mhz() function. MCU uses HSI running at 8 MHz after power-up.
3) This can be a hardware problem. I suggest checking the voltage on PC15. Test it by physically connecting it to GND. Also measure PC14 for comparison. Among these 3 possible causes I can think of, this is the most probable one.

i2c instead of mdio, marvell phy driver

I am trying to run marvell phy linux driver on my custom board.
The driver uses mdio interface, but my board has i2c.
I replaced phy_read()/phy_write() in marvell.c file by i2c read/write functions. It doesn't work. probe function doesn't called, phy subsystem uses mdio for detecting marvell, and cannot detect it.
How can I use i2c in phy linux sysbsystem?
I decided it with mdio-i2c.c module and wrote my own platform driver.
In my driver probe:
new_bus = mdio_i2c_alloc(&pdev->dev, i2c); /* create bridge */
if (!new_bus){
return -ENOMEM;
}
new_bus->name = "marvell mdio i2c bus";
new_bus->parent = &pdev->dev;
err = of_mdiobus_register(new_bus, pdev->dev.of_node);
dts:
mdio_i2c{
compatible = "marvell,i2c-mdio";
i2c-bus = <&i2c_0>;
ethphy1: ethernet-phy#1f {
reg = <0x1f>;
};
};
It's work.
There is one caveat. A marvell88e1111 has 0x5f i2c address. This address is unacceptable for mdio. I set address 0x1f. The mdio-i2c.c module corrects it
static unsigned int i2c_mii_phy_addr(int phy_id)
{
return phy_id + 0x40;
}

Writing PCI driver for DMA transfer on Qemu

I am writing a PCI device on Qemu and driver(LKM) in the guest OS. While Qemu provides an example PCI device, edu(edu.txt and edu.c) with it's distribution, I am having trouble writing the kernel module to do DMA transfer. A basic driver has been covered here but it does not support DMA.
I am following the implementation of the link and this. I tried to transmit buffer to the PCI device from the IRQ handler. The device can read the data (pci_dma_read) but the I am not getting the correct data that I am supposed to receive. Here is the code segment that is doing DMA transfer:
static int write_to_HyPerf(void *dev, void* addr, uint32_t size)
{
/* ----------------------------------------------------------------------------
* PCI address 'addr':
* addr -> DMA source address
* 0x40000 -> DMA destination address
* 100 -> DMA transfer count
* 1 -> DMA command register
* while (DMA command register & 1)
*--------------------------------------------------------------------------------
*/
iowrite32((u32 *)dma_handle_to_device, mmio + IO_DMA_SRC);
iowrite32(DMA_START, mmio + IO_DMA_DST);
iowrite32((u32 *)size, mmio + IO_DMA_XCNT);
iowrite32(DMA_CMD | DMA_IRQ, mmio + IO_DMA_CMD);
}
I also have setup coherent mapping using dma_alloc_coherent.
vaddr_to_device = dma_alloc_coherent(&(dev->dev), DMA_SIZE, &dma_handle_to_device, GFP_ATOMIC);
The complete code is available here. What am I doing wrong?
Could be that you having problem in your driver.
In this case you can use this:
https://github.com/cirosantilli/linux-kernel-module-cheat/blob/master/kernel_modules/qemu_edu.c
and you can use dd command as in this script to write and read from your device:
https://github.com/cirosantilli/linux-kernel-module-cheat/blob/master/rootfs_overlay/lkmc/qemu_edu.sh
Then all you need is to write the wanted dma values to the correct address
like in the edu.c code:
case 0x80:
dma_rw(edu, false, &val, &edu->dma.src, false);
break;
case 0x88:
dma_rw(edu, false, &val, &edu->dma.dst, false);
break;
case 0x90:
dma_rw(edu, false, &val, &edu->dma.cnt, false);
break;
case 0x98:
dma_rw(edu, false, &val, &edu->dma.cmd, false);
break;

Receiving only serial data in the power of 2 when sending the alphabeth

I am trying to perform a simple experiment with an Arduino Uno and the BlueSmirf Bluetooth module from Sparkfun (documentation).
My hardware setup looks like this:
Arduino(power through USB)->BlueSmirf ---(bluetooth)--> PC(no wired connection the the Arduino)->RealTerm
On the Arduino, the following sketch is running:
#include <SoftwareSerial.h>
int txPin = 2;
int rxPin = 3;
SoftwareSerial bluetooth(txPin, rxPin);
void setup() {
bluetooth.begin(115200);
delay(100);
}
void loop() {
String textToSend = "abcdefghijklmnopqrstuvw123456789";
bluetooth.print(textToSend);
delay(5000);
}
Now, the bluetooth connects to the PC just fine, but when I inspect the COM port in RealTerm, I only get the following output:
abdhp1248
Where did the remaining letters and numbers go? It seems like all of the letters that follow the power of two, (i.e. a=1, b=2, d=4, h=8, p=16) print, but none of the rest. Is this just a coincidence?
I think you're running the serial port too fast. As per the comments in the sparkfun BlueSmirf example at https://learn.sparkfun.com/tutorials/using-the-bluesmirf - "115200 can be too fast at times for NewSoftSerial to relay the data reliably".
Reduce the baud rate to 9600 using the code example below, modified from the above web page.
/*
Example Bluetooth Serial Passthrough Sketch
by: Jim Lindblom
SparkFun Electronics
date: February 26, 2013
license: Public domain
This example sketch converts an RN-42 bluetooth module to
communicate at 9600 bps (from 115200), and passes any serial
data between Serial Monitor and bluetooth module.
*/
#include <SoftwareSerial.h>
int bluetoothTx = 2; // TX-O pin of bluetooth mate, Arduino D2
int bluetoothRx = 3; // RX-I pin of bluetooth mate, Arduino D3
SoftwareSerial bluetooth(bluetoothTx, bluetoothRx);
void setup()
{
bluetooth.begin(115200); // The Bluetooth Mate defaults to 115200bps
bluetooth.print("$"); // Print three times individually
bluetooth.print("$");
bluetooth.print("$"); // Enter command mode
delay(100); // Short delay, wait for the Mate to send back CMD
bluetooth.println("U,9600,N"); // Temporarily Change the baudrate to 9600, no parity
// 115200 can be too fast at times for NewSoftSerial to relay the data reliably
bluetooth.begin(9600); // Start bluetooth serial at 9600
}
void loop()
{
String textToSend = "abcdefghijklmnopqrstuvw123456789";
bluetooth.print(textToSend);
delay(5000);
}

RasPi and PIC I2C reading fail

I trying to communicate between RasPi(type B) and PIC16F877 with I2C interface. RasPi is master, PIC is slave. I can send byte of data from RasPi to PIC smoothly. But I need a response from pic after the sending data.
If I try the bus.read_byte_data(address, 0x80) command on python, RasPi close the I2C pins. After this sudo i2cdetect -y 1 command has no device on busline.
Firstly PIC16F877 working with 5V. But I change the voltage to 3.3V (from RasPi) and try again. Its same result.
RasPi Python Code
import smbus
import time
bus = smbus.SMBus(1)
DEVICE_ADDRESS = 0x18
bus.write_byte_data(DEVICE_ADDRESS, 0x00, 1)
time.sleep(0.1)
response = bus.read_byte_data(DEVICE_ADDRESS, 0x80) //IOError: [Errno 5] Input/output error in this line
print response
PIC16F877 CCS C Code
#include <16F877.h>
#device ADC=16
#include <string.h>
#FUSES NOWDT
#FUSES PUT
#FUSES NOLVP
#FUSES NOPROTECT
#FUSES NOBROWNOUT
#use delay(crystal=20000000)
#use FIXED_IO( A_outputs=PIN_A5,PIN_A4,PIN_A3,PIN_A2,PIN_A1,PIN_A0 )
#use FIXED_IO( B_outputs=PIN_B7,PIN_B6,PIN_B5,PIN_B4,PIN_B3,PIN_B2,PIN_B1,PIN_B0 )
#use FIXED_IO( D_outputs=PIN_D7,PIN_D6,PIN_D5,PIN_D4,PIN_D3,PIN_D2,PIN_D1,PIN_D0 )
#use FIXED_IO( E_outputs=PIN_E2,PIN_E1,PIN_E0 )
#use i2c(Slave,Slow,sda=PIN_C4,scl=PIN_C3,force_hw,address=0x30)
char state,temp;
int son_islenen_pin;
void durum_led_iletisim(){
output_high(PIN_B7);
delay_ms(100);
output_low(PIN_B7);
}
void cevap_gonder(int pin){
i2c_write(input(pin));
}
void ac_kapa(int pin){
output_toggle(pin);
}
void islem_yap(char data){
switch(data){
case 1:
ac_kapa(PIN_A0);
break;
case 2:
ac_kapa(PIN_A1);
break;
case 3:
ac_kapa(PIN_A2);
break;
}
}
#INT_SSP
void ssp_interrupt()
{
state = i2c_isr_state();
durum_led_iletisim();
if(state < 0x80)
{
temp = i2c_read()
islem_yap(temp);
son_islenen_pin = temp;
}
else if(temp == 0x80)
{
i2c_write(input(son_islenen_pin));
}
}
void main()
{
enable_interrupts(INT_SSP);
enable_interrupts(GLOBAL);
}
What could be the cause of the problem ? And what would you recommend for a solution ?
I was getting this same error with another device (ADG715 switch matrix I2C), and what I discovered is that there was a RESET pin on the chip that I left floating because the datasheet didn't say anything about it. With the pin floating, the device would be detected by sudo i2cdetect -y 1 just fine, and when I wrote a byte it would usually write properly once and then lose connection and python would throw the same IO errors. Once I pulled it up the device ran properly and python stopped throwing IO errors. Your chip is vastly more complex than mine, but I would still guess that your problem is on the PIC side of the exchange.