Arduino Wire program seems to stop reading bytes after first i2c payload - arduino

I am trying to write a program that receives string data from i2c and displays it on an LCD. The first time data is received to the arduino, it renders it, however subsequent i2c payloads are ignored. My onReceive function has a status line display on the second line of the lcd which display the seconds() field from the timer chip. The seconds number does not seem to increment. However, the per-second dot flash as rendered in loop() does continue to blink, so the mcu is not frozen.
#include <LiquidCrystal.h>
#include <Wire.h>
#include <Time.h>
LiquidCrystal lcd(12, 11, 10, 5, 4, 3, 2);
void setup()
{
Wire.begin(4); // join i2c bus with address #4
Wire.onReceive(receiveEvent); // register event
lcd.begin(16,2); // columns, rows. use 16,2 for a 16x2 LCD, etc.
lcd.clear(); // start with a blank screen
}
void loop()
{
lcd.setCursor(15,1);
if (second() % 2 == 0)
lcd.write(".");
else
lcd.write(" ");
delay(100);
}
void receiveEvent(int howMany)
{
//char buf[howMany];
int i=0;
char output[16];
lcd.clear();
while(Wire.available())
{
char c = Wire.read(); // receive byte as a character
lcd.setCursor(i,0);
lcd.write(c);
i++;
//buf[i++]=c;
//buf[i+1]=0;
}
lcd.setCursor(0,1);
sprintf(output,"s%dNB%dI%d",second(),howMany,i);
lcd.write(output);
}

Your Arduino may be trapped in here:
while(Wire.available())
{
//...
Use:
if(Wire.available() > 0) {
//stuff
}
instead.

Related

use of arduino with can bus sheild

I'm trying to get VGM CAN message out of a Reachstacker 42-45 tonnes
where I am using an arduino MEGA 2560 with a CAN-BUS shield
this my current code:
#include <SPI.h>
#include "mcp_can.h"
// the cs pin of the version after v1.1 is default to D9
// v0.9b and v1.0 is default D10
const int SPI_CS_PIN = 9;
MCP_CAN CAN(SPI_CS_PIN); // Set CS pin
void setup()
{
Serial.begin(115200);
START_INIT:
if(CAN_OK == CAN.begin(CAN_500KBPS)) // init can bus : baudrate = 500k
{
Serial.println("CAN BUS Shield init ok!");
}
else
{
Serial.println("CAN BUS Shield init fail");
Serial.println("Init CAN BUS Shield again");
delay(100);
goto START_INIT;
}
}
void loop()
{
unsigned char len = 0;
unsigned char buf[8];
if(CAN_MSGAVAIL == CAN.checkReceive()) // check if data coming
{
CAN.readMsgBuf(&len, buf); // read data, len: data length, buf: data buf
unsigned char canId = CAN.getCanId();
Serial.println("-----------------------------");
Serial.println("get data from ID: ");
Serial.println(canId);
for(int i = 0; i<len; i++) // print the data
{
Serial.print(buf[i]);
Serial.print("\t");
}
Serial.println();
}
}
this was the result at the time of doing the test, the problem that I do not understand the result
according to the documentation should have a result like this :
this is another part of the documentation :
If someone needs more information or does not understand what I'm looking for, you can request what you need to help me
Send data:
// demo: CAN-BUS Shield, send data
#include <mcp_can.h>
#include <SPI.h>
// the cs pin of the version after v1.1 is default to D9
// v0.9b and v1.0 is default D10
const int SPI_CS_PIN = 9;
MCP_CAN CAN(SPI_CS_PIN); // Set CS pin
void setup()
{
Serial.begin(115200);
START_INIT:
if(CAN_OK == CAN.begin(CAN_500KBPS)) // init can bus : baudrate = 500k
{
Serial.println("CAN BUS Shield init ok!");
}
else
{
Serial.println("CAN BUS Shield init fail");
Serial.println("Init CAN BUS Shield again");
delay(100);
goto START_INIT;
}
}
unsigned char stmp[8] = {0, 1, 2, 3, 4, 5, 6, 7};
void loop()
{
// send data: id = 0x00, standrad frame, data len = 8, stmp: data buf
CAN.sendMsgBuf(0x00, 0, 8, stmp);
delay(100); // send data per 100ms
}
You have two pieces that do not fit between your documentation and the output you are generating:
The data payload
The ID of the CAN frames
For the data payload it is simply a matter of formatting. You print each byte as integer value, whereas in the documentation it is printed as hexadecimal values. Use
Serial.print(buf[i], HEX)
to get the payload printed as hexadecimal characters.
For the ID of the CAN frames, you see from the documentation that they do not fit inside an unsigned char, as already mentioned in the comment by #Guille. Actually those are 29-bit identifiers, which you should ideally store in an appropriately sized variable. Ideally use an unsigned long:
unsigned long canId = CAN.getCanId();
In the documentation the CAN ID is also printed in hexadecimal, so also here use:
Serial.println(canId, HEX);

Working a temprature sensor (LM35) with a GSM module (Sim800L)

I have a temperature sensor set up working with an LCD and a stick to adjust the brightness. I now want the temperature sensor to send a text whenever it reaches a certain temperature. Can somebody please help.
The GSM unit i have is the SIM800L
below is what I have so far :
#include<LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
const int sensor=A1; // Assigning Analog Pin A1 to variable 'sensor'
float tempc; //variable to store temperature in degree Celsius
float tempf; //variable to store temperature in Fahrenheit
float vout; //temporary variable to hold sensor reading
void setup()
{
pinMode(sensor,INPUT); // Configuring pin A1 as INPUT Pin
Serial.begin(9600);
lcd.begin(16,2);
delay(500);
}
void loop()
{
vout=analogRead(sensor);
vout=(vout*500)/1023;
tempc=vout; // Storing value in degrees Celsius
tempf=(vout*1.8)+32; // Converting Temperature value from degrees Celsius to Fahrenheit
lcd.setCursor(0,0);
lcd.print("DegreeC= ");
lcd.print(tempc);
lcd.setCursor(0,1);
lcd.print("Fahrenheit=");
lcd.print(tempf);
delay(1000); //Delay of 1 second for ease of viewing in serial monitor
}
you could use the library Fona to send SMS with a Sim800L
to send a message you use the command -> fona.sendSMS(sendto, message)
#include <SoftwareSerial.h>
#include "Adafruit_FONA.h"
//This part declares that the RX, TX and RST pins of the SIM800L must be connected
//to pin 2, 3 and 4 of the Arduino.
#define FONA_RX 2
#define FONA_TX 3
#define FONA_RST 4
SoftwareSerial fonaSS = SoftwareSerial(FONA_RX, FONA_TX);
Adafruit_FONA fona = Adafruit_FONA(FONA_RST);
void setup() {
while (!Serial);
Serial.begin(115200);
Serial.println(F("FONA basic test"));
Serial.println(F("Initializing....(May take 3 seconds)"));
fonaSS.begin(9600);
if (!fona.begin(fonaSS)) {
Serial.println(F("Couldn't find FONA"));
while (1);
}
Serial.println(F("FONA is OK"));
char sendto[21], message[141];
:
:
//initialize sendto and message
:
:
if (!fona.sendSMS(sendto, message)) {
Serial.println(F("error"));
} else {
Serial.println(F("sent!"));
}
}
to adapt the program to your case: i have put some lines of codes from setup to loop (easy to understant sendto and message definitions in loop now)
#include <SoftwareSerial.h>
#include "Adafruit_FONA.h"
//This part declares that the RX, TX and RST pins of the SIM800L must be connected
//to pin 2, 3 and 4 of the Arduino.
#define FONA_RX 2
#define FONA_TX 3
#define FONA_RST 4
SoftwareSerial fonaSS = SoftwareSerial(FONA_RX, FONA_TX);
Adafruit_FONA fona = Adafruit_FONA(FONA_RST);
void setup() {
fonaSS.begin(9600);
// you initialisation code
}
void loop()
{
vout=analogRead(sensor);
vout=(vout*500)/1023;
tempc=vout; // Storing value in degrees Celsius
tempf=(vout*1.8)+32; // Converting Temperature value from degrees Celsius to Fahrenheit
lcd.setCursor(0,0);
lcd.print("DegreeC= ");
lcd.print(tempc);
lcd.setCursor(0,1);
lcd.print("Fahrenheit=");
lcd.print(tempf);
delay(1000); //Delay of 1 second for ease of viewing in serial monitor
if (tempc > 30.0) {
SendSms();
}
}
void SendSms() {
char sendto[] = "+19999999999"; //put the desired destination phone number for sms here
char message[141];
sprintf(message, "Alert TEMP is %.2f", tempc);// limit to 140
//sends the message via SMS
if (!fona.sendSMS(sendto, message)) {
Serial.println(F("error"));
} else {
Serial.println(F("sent!"));
}
}
another way to send sms
you could test the hayes command: for example
void sendsms(){
Serial.println("Sending text message...");
fonaSS.print("AT+CMGF=1\r"); // SMS MODE
delay(100);
// phone number
fonaSS.print("AT+CMGS=\"+33676171212\"\r"); //indicate your phone number
delay(100);
// message here
fonaSS.print("Message test \r");
// CTR+Z in mode ASCII, to indicate the end of message
fonaSS.print(char(26));
delay(100);
fonaSS.println();
Serial.println("Text send");
}
#include <SoftwareSerial.h>
#include "Adafruit_FONA.h"
//This part declares that the RX, TX and RST pins of the SIM800L must be connected
//to pin 2, 3 and 4 of the Arduino.
#define FONA_RX 2
#define FONA_TX 3
#define FONA_RST 4
SoftwareSerial fonaSS = SoftwareSerial(FONA_TX, FONA_RX);
Adafruit_FONA fona = Adafruit_FONA(FONA_RST);
void setup() {
// you initialisation code
}
void loop()
{
vout=analogRead(sensor);
vout=(vout*500)/1023;
tempc=vout; // Storing value in degrees Celsius
tempf=(vout*1.8)+32; // Converting Temperature value from degrees Celsius to Fahrenheit
lcd.setCursor(0,0);
lcd.print("DegreeC= ");
lcd.print(tempc);
lcd.setCursor(0,1);
lcd.print("Fahrenheit=");
lcd.print(tempf);
delay(1000); //Delay of 1 second for ease of viewing in serial monitor
if (tempc > 30.0) {
SendSms();
}
}
void SendSms() {
char sendto[] = "+19999999999"; //put the desired destination phone number for sms here
char message[141];
sprintf(message, "Alert TEMP is %.2f", tempc);// limit to 140
//sends the message via SMS
if (!fona.sendSMS(sendto, message)) {
Serial.println(F("error"));
} else {
Serial.println(F("sent!"));
}
}

send sms with sim900 using arduino

#include <Password.h>
#include <Keypad.h>
#include <Servo.h>
#include "SIM900.h"
#include <SoftwareSerial.h>
#include "sms.h"
Servo myservo;
Password password = Password( "1234" ); //password to unlock box, can be changed
SMSGSM sms;
int numdata;
boolean started=false;
char smsbuffer[160];
char n[20];
const byte ROWS = 4;
const byte COLS = 4;
// Define the Keymap
char keys[ROWS][COLS] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};
// Connect keypad ROW0, ROW1, ROW2 and ROW3 to these Arduino pins.
byte rowPins[ROWS] = { 9, 8, 7, 6 };// Connect keypad COL0, COL1 and COL2 to these Arduino pins.
byte colPins[COLS] = { 5, 4, 3, 2 };
int x=0;
// Create the Keypad
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
void setup() //if i add sms(); function it workssss
{
Serial.begin(9600); //Start a Serial COM
Serial.println(F("ARDUINO SECURITY SYSTEM V1.0"));
Serial.print(F("Checking GSM COM..."));
if (gsm.begin(9600)) //Start the GSM COM
{
(sms.SendSMS("+XXXXX","Your Home Security system is powered up"));
Serial.println(F("Good To GO!!"));
}
else
{
Serial.println(F("Could not connect to GSM modem"));
}
Serial.write(254);
Serial.write(0x01);
delay(200);
pinMode(11, OUTPUT); //green light
pinMode(12, OUTPUT); //red light
myservo.attach(13); //servo on digital pin 9 //servo
keypad.addEventListener(keypadEvent);//add an event listener for this keypad
}
void loop(){
keypad.getKey();
myservo.write(0);
}
//take care of some special events
void keypadEvent(KeypadEvent eKey){
switch (keypad.getState()){
case PRESSED:
Serial.print("Enter : ");
Serial.println(eKey);
delay(10);
Serial.write(254);
switch (eKey){
case 'A': checkPassword(); delay(1); break;
case 'C': checkPassword(); delay(1); break;
case 'D': checkPassword(); delay(1); break;
case 'B': password.reset(); delay(1); break;
case '*': checkPassword(); break;
case '#': password.reset(); break;
default: password.append(eKey); delay(1);
}
}
}
void checkPassword(){
if (password.evaluate()){ //if password is right open box
Serial.println("Accepted");
Serial.write(254);delay(50);
//Add code to run if it works
myservo.write(5); //160deg
digitalWrite(11, HIGH);//turn on
delay(2000); //wait 5 seconds
digitalWrite(11, LOW);// turn off
}
else
{
Serial.println("Denied"); //if passwords wrong keep box locked
Serial.write(254);delay(10);
x++;
if(x==3)
//add code to run if it did not work
{
myservo.write(0);
digitalWrite(12, HIGH);
delay(500);
digitalWrite(12, LOW);
if (gsm.begin(9600))
{
(sms.SendSMS("+XXXXX","Your Home Security system is being bridged"));
Serial.println("USER WARNED");
}
}
}
}
;
}
In the picture the same code doesn't seem to work when I place the lines
if (gsm.begin(9600)) //Start the GSM COM
{
(sms.SendSMS("+8613668914901","Your Home Security system is being bridged"));
but this lines work great inside the void setup function.
How can I fix this problem? Inside the void setup the sketch works fine but when I also put the code in the function CheckPassword it doesn't send SMS.
I also tried to create a function let's say void SMS and call it in the checkPassword function but it doesn't solve the problem, btw the same function when called in the void setup works fine.
You are supposed to initialize the gsm only once, in the setup function.
In your code you attempt to initialize it again in the checkPassword method, and that is obviously not going to work.
Thus you should remove the line gsm.begin(9600) from the checkPassword function.
UPDATE 1:
In your scheme you reserve the pins 9, 8, 7, 6, 5, 4, 3, 2 for the Keyboard. However, at the same time you reserve pins 2, 3 for your GSM module (see GSM.cpp):
#define _GSM_TXPIN_ 2
#define _GSM_RXPIN_ 3
Using the same pins for multiple purposes can often result (if not done properly) in undefined behaviour which in the best scenario means that your sketch isn't doing what it is supposed to do, and in the worst scenario it might damage your components.
You are already using pins 0, 1 for the Serial library, but according to your code the pins 10, 11, 13 should still be free if you want to relocate the existing pins to your components.
Notice also the following warnings inside the GSM library:
[3] My shield doesn't work. Why?
Check this steps and then ask for support on the issues' page on google
code.
1) SIM900 and SIM908 require about 1 A during the hardest tasks.
You should have an external power source that can provide about
1 A at 8-12 V
2) If the SIM90X blinks (1 Hz) for some seconds and then turn off,
probably it's a communication's problem. Check the switch/jumpers
for Serial communication.
3) Arduino Uno has 2 KB of RAM. Library takes about 80% (we are working
to reduce it), if you use more than 20% left, Arduino can restart
or print on serial strange strings.
4) Check the jumper of communication, power source (battery or externel) and charge.

Read/Write EEPROM Arduino

I have a new ATmega328P CH340G Arduino Uno R3 board.
When I input a two-digit number (like 29), after power off and power on, the board shows only one digit (only 9). I want to show two digits.
enter image description here
Can you help me?
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#include <EEPROM.h>
int addr = 5;
LiquidCrystal_I2C lcd(0x27,16,2);
void setup() {
lcd.init();
Serial.begin(9600);
// initialize the lcd
// Print a message to the LCD.
lcd.backlight();
lcd.setCursor(0,0);
lcd.write(EEPROM.read(addr));
}
void loop() {
if (Serial.available()) {
while (Serial.available() > 0) {
char myValue = Serial.read();
EEPROM.write(addr,myValue);
lcd.write(myValue);
}
}
}
You are always writing to the same addr (i.e. 5) so you are most likely overwriting the previous character. Try incrementing your address after a write like this:
EEPROM.write(addr++, myValue);
(notice the ++ to increment the address)

Unable to receive correct data using i2c serial communication between two Arduino

I'm using an i2c serial bus for communication between two Arduino (Uno = Master, Due = Slave) and I'm currently experiencing problems while reading data received by the slave.
The master sends some data using Wire.write(command). The slave receives it and the handler function receiveEvent(int howMany) is called thanks the instruction Wire.onReceive(receiveEvent).
Here is the simplified code for the serial communication:
Master's Sketch
#include <Wire.h>
void setup() {
Wire.begin();
Serial.begin(9600);
}
void loop() {
Wire.beginTransmission(8);
byte command[] = {2, 5, 3};
Wire.write(command, 3);
Wire.endTransmission();
Serial.println("command sent...");
delay(1000);
}
Slave's Sketch
#include <Wire.h>
int c = 0;
void setup() {
Serial.begin(9600);
Wire.begin(8);
Wire.onReceive(receiveEvent);
}
void loop() {
delay(1000);
}
void receiveEvent(int howManyBytes){
for(int iter=0; iter<howMany; iter++){
c = Serial.read();
Serial.print("c : ");
Serial.println(c);
}
}
Slave's Output
c : -1
c : -1
c : -1
It appears that three bytes are received but the data are not transmitted correctly. Any idea were there could be a mistake or a bug? Thanks!
Since you expect the data from the Wire, I think your slave should receive the data via Wire.read() instead of Serial.read().

Resources