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

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);
}

Related

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?

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.

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;
}

(GSM module SM5100B + ATMEGA16A interface) Trouble sending SMS using AT commands in C code

I am having trouble with my university project for embedded systems. The goal is to establish an interface between a SM5100B GSM module and ATMEGA16A microcontroller, using UART (which I did, using the correct ports from the datasheets), and to be able to send/receive simple SMS messages by sending AT commands trough the Tx and Rx ports from atmega to gsm and vice versa, via C code in Atmel.(not using hyperterminal)
When I tested the GSM module using TeraTerm, i was able to connect properly, and send AT commands easily, also managed to send and recieve an SMS with the SIM card inserted, so everything works fine.
Now I'm trying to do that using the microcontroller.
Here is the code I have so far:
#define F_CPU 7372800UL
#include <stdio.h>
#include <stdlib.h>
#include <util/delay.h>
#include <avr/io.h>
#include <string.h>
#define BAUD 9600
#define MYUBRR ((F_CPU/16/BAUD)-1) //BAUD PRESCALAR (for Asynch. mode)
void GSM_init(unsigned int ubrr ) {
/* Set baud rate */
UBRRH = (unsigned char)(ubrr>>8);
UBRRL = (unsigned char)ubrr;
/* Enable receiver and transmitter */
UCSRB = (1<<RXEN)|(1<<TXEN);
/* Set frame format: 8data, 2stop bit */
UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0);
}
void USART_Transmit(char data ) {
/* Wait for empty transmit buffer */
while ( !( UCSRA & (1<<UDRE)) );
/* Put data into buffer, sends the data */
UDR = data;
}
void USART_Transmits(char data[] ) {
int i;
for(i=0; i<strlen(data); i++) {
USART_Transmit(data[i]);
_delay_ms(300);
}
}
int main(void)
{
GSM_init(MYUBRR);
char text_mode[] = "AT+CMGF=1";
char send_sms[] = "AT+CMGS=";
char phone_number[] = "00385*********";
char sms[] = "gsm sadness";
USART_Transmits(text_mode);
_delay_ms(1000);
USART_Transmits(send_sms);
_delay_ms(1000);
USART_Transmit(34);//quotation mark "
//_delay_ms(300);
USART_Transmits(phone_number);
//_delay_ms(300);
USART_Transmit(34);//quotation mark "
//_delay_ms(300);
USART_Transmit(13);//enter
//_delay_ms(300);
USART_Transmits(sms);
_delay_ms(1000);
USART_Transmit(26);//ctrl+z
_delay_ms(300);
USART_Transmit(13);//enter
_delay_ms(3000);
while (1)
{
}
}
However, my code isn't working, it's not sending the message.
The functions for transmitting are taken from the datasheet and everywhere on the internet I search I find the same ones over and over again.
Is the problem in AT responses that I'm not reading correctly? Or in parsing AT commands to the serial port?
Can anybody help me understand where I'm going wrong with this, or where I can look for to understand how to make this work?

How to find the device id of a STM32F103RET

I have been told that each STM32F103RET devices carry a unique device id.If so what is the procedure to retrieve the ID?I am running a system wherein I communicate with more than one STM borads. To differentiate each STM board I can use this unique Id.
thanks
You can find this information in STM32F103 Reference Manual. More specifically, you want to read chapter 30.2 Unique device ID register (96 bits).
So your device ID contained in read-only register, called U_ID. This register address is 0x1ffff7e8. It's 96 bits long, so it can be read (for example) using 3 read operations, each 32-bit long. Of course you can't hold it in one variable. So you should come up with some way of storing it in memory. It can be array, or structure, etc.
I would probably use structure for this purpose, using offsets described in Reference Manual:
#include <stdint.h>
struct u_id {
uint16_t off0;
uint16_t off2;
uint32_t off4;
uint32_t off8;
};
How to read it is up to you (depends on which framework you are using, e.g. in libopencm3 you have MMIO32 macro for this). In general case I would do something like that:
#define MMIO16(addr) (*(volatile uint16_t *)(addr))
#define MMIO32(addr) (*(volatile uint32_t *)(addr))
#define U_ID 0x1ffff7e8
/* Read U_ID register */
void uid_read(struct u_id *id)
{
id->off0 = MMIO16(U_ID + 0x0);
id->off2 = MMIO16(U_ID + 0x2);
id->off4 = MMIO32(U_ID + 0x4);
id->off8 = MMIO32(U_ID + 0x8);
}
You will also need a function to compare two IDs. You can either use memcmp() or some custom function for that matter. I'd prefer a custom one in this case:
#include <stdbool.h>
/* Returns true if IDs are the same */
bool uid_cmp(struct u_id *id1, struct u_id *id2)
{
return id1->off0 == id2->off0 &&
id1->off2 == id2->off2 &&
id1->off4 == id2->off4 &&
id1->off8 == id2->off8;
}
You can use it like that:
int main(void)
{
struct u_id id1 = { 0x0, 0x1, 0x2, 0x3 };
struct u_id id2;
bool same_id;
uid_read(&id2);
same_id = uid_cmp(&id1, &id2);
printf("%s\n", same_id ? "equal" : "not equal");
return 0;
}
UPDATE
As I understand your situation:
Each of your boards should send some interrupt to your master board (more specifically, to GPIO pin on master board).
Once master board received interrupt, it initiates transfer (request) to board where interrupt came from (probably using I2C, SPI, UART or something like that to communicate between boards).
Then client board responds with it's device ID.
Interrupts are handled sequentially, so device IDs will be obtained one by one.
Picture below illustrates case with I2C bus used for ID transmission.
For board 1 you will have GPIO1 interrupt handler executed, for board 2 -- GPIO 2 interrupt handler. Hence you know which one to ask for device ID. So device ID will be obtained one at a time. From here you can figure out how to store those IDs. I propose to use regular array:
struct u_id device_ids[2];
Here is pseudo-code showing how to populate this array:
void gpio1_isr(void)
{
uint8_t i2c_buf[12];
i2c_get(i2c_buf);
memcpy(&device_ids[0], i2c_buf, 12);
}
void gpio2_isr(void)
{
uint8_t i2c_buf[12];
i2c_get(i2c_buf);
memcpy(&device_ids[1], i2c_buf, 12);
}
(isr stands for Interrupt Service Routine, which is the same as interrupt handler).
In case you are sure that your two client boards are ready for I2C transfer in a time when master board is gonna ask them for IDs, you can get rid of 2 GPIO lines and just use I2C transactions from master board to clients whenever you want.
Open a notepad and write this:
openocd -f interface/jlink.cfg -f board/olimex_stm32_h103.cfg -c "init" -c "stm32f1x.cpu mdw 0x1FFFF7E8 3" -c "exit"
#pause
Then save it as ".bat" file then run it!