I2C Stops Transmitting After Exactly 7 Requests with Arduino - arduino

I am using an ATTiny85 running the TinyWire library to communicate with an Arduino Uno running the Wire library, from an I2C connection. I can transmit one byte at a time perfectly fine for as many requests as I want, however a problem arises when I try and send two bytes at a time. Below is the code I am using (note - I am using a popular modified version of the TinyWire library which has the OnRequest method implemented). Here's my code for the slave:
#include "TinyWireS.h" // wrapper class for I2C slave routines
#define I2C_SLAVE_ADDR 0x27 // i2c slave address
void setup()
{
TinyWireS.begin(I2C_SLAVE_ADDR); // init I2C Slave mode
TinyWireS.onRequest(requestEvent);
}
void loop()
{
}
void requestEvent()
{
int16_t bigNum = analogRead(3);
byte myArray[2];
myArray[0] = (bigNum >> 8) & 0xFF;
myArray[1] = bigNum & 0xFF;
TinyWireS.send(myArray[0]);
TinyWireS.send(myArray[1]);
}
and for the master:
#include <Wire.h>
#define DEVICE_2 0x27
void setup()
{
Wire.begin();
Serial.begin(9600);
}
void loop()
{
delay(2000);
int16_t bigNum;
byte a,b;
// read 2 bytes, from address 0x27
Serial.println("Request Start");
Wire.requestFrom(DEVICE_2, 2);
a = Wire.read();
b = Wire.read();
bigNum = a;
bigNum = bigNum << 8 | b;
Serial.print(bigNum);
Serial.print("\n");
}
Regardless of the delay time, I can always only get exactly 7 requests. I've tried many values from no delay to 5 second delays in between calls. If I power off the ATTiny, then supply power again while the Uno is still connected to the Serial port, I can get 7 more requests before stopping again. The Serial monitor always shows that the Uno's main loop somehow gets paused directly after calling requestFrom(), which makes it look to me like it's waiting for something, but I can't figure out what. When I unplug the ATTiny, the Uno prints to the Serial port -28412. I have also tried putting the following before reading from the buffer:
if(Wire.available() > 0) {
a = Wire.read();
b = Wire.read();
}
Thanks for your help.

According to this Issue, you can only send one byte from the onRequest callback function. It is called from the ISR, so it really shouldn't do very much. He suggests remembering which byte has been sent, then send the next one when another request event happens. See this example.

Related

SMS notification not working with Arduino Nano with a GSM module

I want to use an Arduino Nano to monitor SMS traffic of a GSM module. I'm able to read and send SMS but the notification system is not working: when I send an SMS (to the SIM card that is in the GSM module) no new data becomes available in the Serial port. Any idea why or how can I debug to find the problem?
The communication is done through pins 9 and 10 of Arduino and RX and TX for the GSM module, which is an Quectel EC25. The code I'm using:
#include <SoftwareSerial.h>
#define DEBUG Serial
SoftwareSerial EC25(10,9); // RX, TX - 9600 baud rate
// pin 8 of raspi -> pin 9 of arduino nano
// pin 10 of raspi -> pin 10 of arduino nano
#define AT_RESPONSE_LEN 100
#define TIMEOUT 1000
void setup() {
// put your setup code here, to run once:
EC25.begin(9600);
DEBUG.begin(9600);
// some AT commands just to see if the coms are ok
sendATComm("AT","OK\r\n");
sendATComm("AT+IPR?","OK\r\n");
sendATComm("AT+CGSN","OK\r\n");
sendATComm("AT+CNMI=2,1,0,0,0","OK\r\n");
DEBUG.println("listennig");
}
void loop() {
// put your main code here, to run repeatedly:
if (EC25.available()){
DEBUG.println("Notification received!");
}
}
// function for sending at command.
const char* sendATComm(const char *command, const char *desired_reponse)
{
uint32_t timer;
char response[AT_RESPONSE_LEN]; // module response for AT commands.
memset(response, 0 , AT_RESPONSE_LEN);
EC25.flush();
sendATCommOnce(command);
timer = millis();
while(true){
if(millis()-timer > TIMEOUT){
sendATCommOnce(command);
timer = millis();
}
char c;
int i = 0;
while(EC25.available()){
c = EC25.read();
DEBUG.write(c);
response[i++]=c;
delay(2);
}
if(strstr(response, desired_reponse)){
return response;
memset(response, 0 , strlen(response));
break;
}
}
}
// send at comamand to module
void sendATCommOnce(const char *comm)
{
EC25.print(comm);
EC25.print("\r");
delay(100);
}
So, it turns out that I had to define the output port of URC to use UART communication (not using it as default).
The default configuration was set to either usbat or usbmodem, meaning that the notification information I was waiting for was being sent to one of these serial ports. But I was listening to UART (through RX and TX pints) and therefore I was not getting any notification.
AT command QURCCFG can be used to set which port URC signals should be sent to. In this case I want them to be sent to UART:
AT+QURCCFG="urcport","uart1"

use another serial to send data from arduino to processing

i need to use another serial to send data from arduino teensy to processing because default serial (Serial.begin(9600)) already used for big program
i try to read some reference about how maybe i can change from which serial i want to receive (https://processing.org/reference/libraries/serial/Serial.html), but i dont think it can be change
void setup() {
Serial.begin(115200); // already used
Serial2.begin(9600); // processing
}
void loop() {
Serial.println("...") //big code that i am not allow to change
Serial2.println("hello world");
delay(1000);
}
i expected to get "hello world" in my processing repeatly, but i really dont have any idea how to write the code so i can get value from Serial2 instead from Serial
It depends on what Teensy module you are using and how you're doing the wiring.
Please see the Teensy Using the Hardware Serial Ports article for more details.
If possible I'd try their UART/USB example:
// set this to the hardware serial port you wish to use
#define HWSERIAL Serial1
void setup() {
Serial.begin(9600);
HWSERIAL.begin(9600);
}
void loop() {
int incomingByte;
if (Serial.available() > 0) {
incomingByte = Serial.read();
Serial.print("USB received: ");
Serial.println(incomingByte, DEC);
HWSERIAL.print("USB received:");
HWSERIAL.println(incomingByte, DEC);
}
if (HWSERIAL.available() > 0) {
incomingByte = HWSERIAL.read();
Serial.print("UART received: ");
Serial.println(incomingByte, DEC);
HWSERIAL.print("UART received:");
HWSERIAL.println(incomingByte, DEC);
}
}
If that hows with the same USB connection at the same time, negotiate with your colleague so you get to use the easier one that simply shows up as another Serial port in Processing.
If that is not an option:
double check the pinout the Serial Ports article above but also the logic level voltage (e.g. might be 3.3V, not 5V)
get a USB Serial converter (for the right logic level) - this will show up as a different Serial port using Processing's Serial.list()
connect Serial2's TX pin to the convertor's RX pin and read the data in Processing (similar to process to how you'd read Serial, just a different port name)

Arduino LORA Send and Receive Data

I tried to allow sending and receiving data using 2 Arduino Unos, 2 LORA chips (SX1278 433MHz), 2 antennas and 2 Arduino IDE.
Problem is with the receiving data command.
This is the code for SENDING command:
#include <SPI.h>
#include <LoRa.h>
int counter = 0;
const int ss = 10;
const int reset = 9;
const int dio0 = 2;
void setup() {
Serial.begin(9600);
LoRa.begin(433E6);
LoRa.setPins(ss, reset, dio0);
while (!Serial);
Serial.println("LoRa Sender");
}
void loop() {
Serial.print("Sending packet: ");
Serial.println(counter);
// send packet
LoRa.beginPacket();
LoRa.print("hello ");
LoRa.print(counter);
LoRa.endPacket();
counter++;
delay(5000);
}
On serial monitor, I succeed in sending packages, but not receiving. This is the RECEIVING code:
#include <SPI.h>
#include <LoRa.h>
const int ss = 10;
const int reset = 9;
const int dio0 = 2;
void setup() {
Serial.begin(9600);
LoRa.begin(433E6);
LoRa.setPins(ss, reset, dio0);
while (!Serial);
Serial.println("LoRa Receiver");
}
void loop() {
// try to parse packet
int packetSize = LoRa.parsePacket();
if (packetSize) {
// received a packet
Serial.print("Received packet '");
// read packet
while (LoRa.available()) {
Serial.print((char)LoRa.read());
Serial.print("hello ");
}
// print RSSI of packet
Serial.print("' with RSSI ");
Serial.println(LoRa.packetRssi());
}
}
I used instructions about connections from this git page:
https://github.com/sandeepmistry/arduino-LoRa
To make this board work, I had to explicitly initialize SPI
SPI.begin(/*sck*/ 5, /*miso*/ 19, /*mosi*/ 27, /*ss*/ cs);
It may be the same for yours. Also, you should properly initialize Lora:
while (!LoRa.begin(433E6)) {
Serial.print(".");
delay(500);
}
Serial.println("LoRa Initializing OK!");
With the code you posted, you don't really know if it initialized correcly or if it's actually sending any data.
First I haven't worked with Lora library. I worked with SX1278 libaray. So I can help you with that.
At first here is the link to the libaray - Lora SX1278.h library
Now you might ask why I'm not using the library from the original GitHub repo. Well I faced issue with that library and the issue is this:
The sx1278::getPacket() library function is modified to stabilize the Lora receive functionality. There was a bug which led the esp to panic. The payloadlength read from the REG_FIFO register was not checked for valid value which led to reading the REG_FIFO register read for over 65000 times. Moreover yield() is added in time consuming parts of this function.
That is why I'm using this custom library. Anyway, for you:
You can use this function to send packet:
T_packet_state = sx1278.sendPacketTimeoutACK(ControllerAddress, message); //T_packet_state is 0 if the packet data is sent successful.
Also to receive data use this function:
R_packet_state = sx1278.receivePacketTimeoutACK(); //R_packet_state is 0 if the packet data is received successfully.
And at the beginning of the code just define this few things:
//Lora SX1278:
#define LORA_MODE 10 //Add your suitable mode from the library
#define LORA_CHANNEL CH_6_BW_125 //Ch number and Bandwidth
#define LORA_ADDRESS 3 //Address of the device from which you will send data
uint8_t ControllerAddress = 5; //Address of receiving end device
My first decent answer on StackOverflow. Finger Crossed

ESP8266 to ESP8266 i2C Communication

I am trying to get my ESP8266's connect and send messages over an i2c bus. I am using a NodeMcu Development Board. Pins D1,D2 and GND are connected to each other.
The code on my master is :
#include <Wire.h>
void setup() {
Wire.begin(D1,D2); // join i2c bus (address optional for master)
Serial.begin(115200);
}
byte x = 0;
void loop() {
Wire.beginTransmission(8);
Wire.write(x); // sends one byte
Wire.endTransmission(); // stop transmitting
Serial.println("Transmitted");
x++;
delay(500);
}
And the code on my slave ESP is:
#include <Wire.h>
void setup() {
Wire.begin(8); // join i2c bus with address #8
Wire.onReceive(receiveEvent); // register event
Serial.begin(115200); // start serial for output
}
void loop() {
delay(100);
}
// function that executes whenever data is received from master
// this function is registered as an event, see setup()
void receiveEvent(int howMany) {
Serial.println("Received..");
/*
while (1 < Wire.available()) { // loop through all but the last
char c = Wire.read(); // receive byte as a character
Serial.print(c); // print the character
}
*/
int x = Wire.read(); // receive byte as an integer
Serial.println(x); // print the integer
}
Running this gives no output on the receiver chip.
As mentioned in the comments it doesn't look like I2C is supported, but you could use PJON
You just need to connect a single wire to enable communication between the two devices
I'm not sure but I would expect the Wire library from Arduino to use the hardware I2C controller for ATMega. The I2C driver in the firmware from Espressif seems to be doing I2C over GPIO, that would hint there is no hw controller on ESP (what are the odds they would be the same anyway). So you need to use something else than Wire.h, thus I would suggest - try downloading something that fakes I2C over GPIO for your Arduino IDE. Like this .. maybe, I haven't tried that out. I know not a complete solution, but maybe at least this helps.. good luck!
ESP8266(I2C Master) to ESP8266(I2C Slave) works from version 2.5.0. Check out my comments on the ESP8266 GitHub

PC to Arduino RS-485 connection via converters

I'm trying to make modbus RS-485 connection between PC (Windows) and Arduino.
On the PC side I use USB-to-RS485 converter like this one http://ru.aliexpress.com/item/USB-to-485-RS485-converter-Adapter-Support-Windows-7-8-for-Arduino/1577970568.html
On the Arduino side I use TTL-to-RS-485 like this one http://ru.aliexpress.com/item/5pcs-lot-MAX485-Module-RS-485-TTL-to-RS485-Module-for-Arduino/32262338107.html
Problem1:
When I send byte from PC to Arduino. Nothing happens. Arduino does not receive anything. In this case i upload to Arduino this code:
#include <SoftwareSerial.h>
#include "RS485_protocol.h"
SoftwareSerial rs485 (10, 11); // receive pin, transmit pin
const byte ENABLE_PIN = 3;
void setup()
{
Serial.begin(9600);
rs485.begin (28800);
pinMode (ENABLE_PIN, OUTPUT); // driver output enable
}
void loop()
{
byte buf [1];
byte received = recvMsg (fAvailable, fRead, buf, sizeof (buf));
if (received)
{
Serial.println(buf[0]);
} else {
Serial.println("--");
}
} // end of loop
int fAvailable ()
{
return rs485.available ();
}
int fRead ()
{
return rs485.read ();
}
And open Serial Monitor in Arduino IDE to show received data.
Then I open new instance of Arduino IDE, chose proper USB-to-RS485 COM port and opens it Serial Monitor to send some data.
So in Arduino side Serial Monitor I see only "--" lines. Even when I'm trying to send something in PC side Serial Monitor.
The other problem is:
Vice versa. When i sending some byte from Arduino to PC I receive some odd symbols instead sent byte.
The Arduino code in this case is:
#include <SoftwareSerial.h>
#include "RS485_protocol.h"
SoftwareSerial rs485 (10, 11); // receive pin, transmit pin
const byte ENABLE_PIN = 3;
void setup()
{
rs485.begin (28800);
pinMode (ENABLE_PIN, OUTPUT); // driver output enable
}
void loop()
{
byte msg[1] = {3};
sendMsg(msg);
} // end of loop
void sendMsg(byte msg[])
{
delay (1); // give the master a moment to prepare to receive
digitalWrite (ENABLE_PIN, HIGH); // enable sending
sendMsg (fWrite, msg, 1);
digitalWrite (ENABLE_PIN, LOW); // disable sending
}
void fWrite (const byte what)
{
rs485.write (what);
}
int fAvailable ()
{
return rs485.available ();
}
On the PC side (in the Arduino IDEs Serial Monitor) I receive odd symbols instead "3" symbol.
=======
RS485 converters wired with twisted pare A to A and B to B.
RS485 to TTL converter connected to Arduino properly. (Communication between two arduinos works fine).
Please help.
Example of RS485 :
Using a SN75176 IC.
RE (pin 2) connect to ground (for always reading )
Arduino control only DE PIN for writing data
But PC side problems:
Where bridged DE pins ? (CTS,DTR,RTD if supported)
What is your flow control ? (related #1)
Did you connect any resistor to A, B pin ?<+5V>----[560R]-----(A)----[120R]-----(B)------[560R]------<-5V> So mean line end
Did you filter DE Pin 2 signal (for noise)
A tricks : Use SN75176 on arduino side because this IC a RS232(UART) to (RS485) converter.
Edit : Modbus got 2 type on serial (RTU, ASCII). Dont care RS232/485 differences because different signal, same protocol.
Example packet type:
ASCII : :010300200004+CRC+FE(crc =packet check code, fe=end delimeter)
RTU : \x01\x03\x00\x20\x00\x04\x +CRC
On rtu : every byte need 1.5 char space and without start and end delimeter.
And Modbus node type meaning master and slave.
I hope helpfull.

Resources