Multitech mDot ARMmBed platform i2c communication with Arduino - arduino

I am not able to retrieve data from i2c bus from an Arduino to a mDot LoRa node. Based on the ARMBed i2c library tried to get data from the Arduino (which is the slave) using this code:
/**
* Copyright (c) 2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdio.h>
#include "lorawan/LoRaWANInterface.h"
#include "lorawan/system/lorawan_data_structures.h"
#include "events/EventQueue.h"
// Application helpers
#include "DummySensor.h"
#include "trace_helper.h"
#include "lora_radio_helper.h"
using namespace events;
// documentacion de i2c
// https://os.mbed.com/docs/mbed-os/v5.12/apis/i2c.html
#include "mbed.h"
mbed::I2C i2c(I2C_SDA, I2C_SCL);
const int addr7bit = 0x29; // 7-bit I2C address (del ARDUINO)
const int addr8bit = addr7bit << 1; // 8-bit I2C address (shift a izquierda para el MDOT)
// Max payload size can be LORAMAC_PHY_MAXPAYLOAD.
// This example only communicates with much shorter messages (<30 bytes).
// If longer messages are used, these buffers must be changed accordingly.
uint8_t tx_buffer[30];
uint8_t rx_buffer[30];
/*
* Sets up an application dependent transmission timer in ms. Used only when Duty Cycling is off for testing
*/
#define TX_TIMER 10000
/**
* Maximum number of events for the event queue.
* 10 is the safe number for the stack events, however, if application
* also uses the queue for whatever purposes, this number should be increased.
*/
#define MAX_NUMBER_OF_EVENTS 10
/**
* Maximum number of retries for CONFIRMED messages before giving up
*/
#define CONFIRMED_MSG_RETRY_COUNTER 3
/**
* Dummy pin for dummy sensor
*/
#define PC_9 0
/**
* Dummy sensor class object
*/
DS1820 ds1820(PC_9);
/**
* This event queue is the global event queue for both the
* application and stack. To conserve memory, the stack is designed to run
* in the same thread as the application and the application is responsible for
* providing an event queue to the stack that will be used for ISR deferment as
* well as application information event queuing.
*/
static EventQueue ev_queue(MAX_NUMBER_OF_EVENTS *EVENTS_EVENT_SIZE);
/**
* Event handler.
*
* This will be passed to the LoRaWAN stack to queue events for the
* application which in turn drive the application.
*/
static void lora_event_handler(lorawan_event_t event);
/**
* Constructing Mbed LoRaWANInterface and passing it the radio object from lora_radio_helper.
*/
static LoRaWANInterface lorawan(radio);
/**
* Application specific callbacks
*/
static lorawan_app_callbacks_t callbacks;
/**
* Entry point for application
*/
int main(void)
{
// setup tracing
setup_trace();
// stores the status of a call to LoRaWAN protocol
lorawan_status_t retcode;
// Initialize LoRaWAN stack
if (lorawan.initialize(&ev_queue) != LORAWAN_STATUS_OK) {
printf("\r\n LoRa initialization failed! \r\n");
return -1;
}
printf("\r\n Mbed LoRaWANStack initialized \r\n");
// prepare application callbacks
callbacks.events = mbed::callback(lora_event_handler);
lorawan.add_app_callbacks(&callbacks);
// Set number of retries in case of CONFIRMED messages
if (lorawan.set_confirmed_msg_retries(CONFIRMED_MSG_RETRY_COUNTER)
!= LORAWAN_STATUS_OK) {
printf("\r\n set_confirmed_msg_retries failed! \r\n\r\n");
return -1;
}
printf("\r\n CONFIRMED message retries : %d \r\n",
CONFIRMED_MSG_RETRY_COUNTER);
// Enable adaptive data rate
if (lorawan.enable_adaptive_datarate() != LORAWAN_STATUS_OK) {
printf("\r\n enable_adaptive_datarate failed! \r\n");
return -1;
}
printf("\r\n Adaptive data rate (ADR) - Enabled \r\n");
retcode = lorawan.connect();
if (retcode == LORAWAN_STATUS_OK ||
retcode == LORAWAN_STATUS_CONNECT_IN_PROGRESS) {
} else {
printf("\r\n Connection error, code = %d \r\n", retcode);
return -1;
}
printf("\r\n Connection - In Progress ...\r\n");
// make your event queue dispatching events forever
ev_queue.dispatch_forever();
return 0;
}
/**
* Sends a message to the Network Server
*/
static void send_message()
{
uint16_t packet_len;
int16_t retcode;
float sensor_value;
// esta sería la variable que guardará el "paquete" leido del ARDUINO
char cmd[28];
// inicializamos en 0 cada valor del arreglo
for (size_t i = 0; i < 28; i++)
{
cmd[i] = 0x00;
}
if (ds1820.begin()) {
ds1820.startConversion();
sensor_value = ds1820.read();
printf("\r\n Esto es console log = %3.1f \r\n", sensor_value);
ds1820.startConversion();
packet_len = sprintf((char *) tx_buffer, "Esto es lo que se manda: %3.1f", sensor_value); //28 bytes
} else {
// printf("\r\n No sensor found \r\n");
// return;
// basicamente tengo que mandar cualquier cosa para que el maestro me conteste con los datos
// de los sensores.
i2c.write(addr8bit, cmd, 28);
printf("%d\n", addr7bit);
printf("%d\n", addr8bit);
wait(5); // 5 segundos
// y ahora leo los 28 bytes recibidos, el paquete enviado desde arduino deberia ser de 28 bytes
i2c.read(addr8bit, cmd, 28);
printf("%s\r\n", cmd);
packet_len = sprintf((char *) tx_buffer, "%s", cmd);
}
retcode = lorawan.send(MBED_CONF_LORA_APP_PORT, tx_buffer, packet_len, MSG_UNCONFIRMED_FLAG);
if (retcode < 0) {
retcode == LORAWAN_STATUS_WOULD_BLOCK ? printf("send - WOULD BLOCK\r\n")
: printf("\r\n send() - Error code %d \r\n", retcode);
if (retcode == LORAWAN_STATUS_WOULD_BLOCK) {
//retry in 3 seconds
if (MBED_CONF_LORA_DUTY_CYCLE_ON) {
ev_queue.call_in(3000, send_message);
}
}
return;
}
printf("\r\n %d bytes scheduled for transmission \r\n", retcode);
memset(tx_buffer, 0, sizeof(tx_buffer));
}
/**
* Receive a message from the Network Server
*/
static void receive_message()
{
uint8_t port;
int flags;
int16_t retcode = lorawan.receive(rx_buffer, sizeof(rx_buffer), port, flags);
if (retcode < 0) {
printf("\r\n receive() - Error code %d \r\n", retcode);
return;
}
printf(" RX Data on port %u (%d bytes): ", port, retcode);
for (uint8_t i = 0; i < retcode; i++) {
printf("%02x ", rx_buffer[i]);
}
printf("\r\n");
memset(rx_buffer, 0, sizeof(rx_buffer));
}
/**
* Event handler
*/
static void lora_event_handler(lorawan_event_t event)
{
switch (event) {
case CONNECTED:
printf("\r\n Connection - Successful \r\n");
if (MBED_CONF_LORA_DUTY_CYCLE_ON) {
send_message();
} else {
ev_queue.call_every(TX_TIMER, send_message);
}
break;
case DISCONNECTED:
ev_queue.break_dispatch();
printf("\r\n Disconnected Successfully \r\n");
break;
case TX_DONE:
printf("\r\n Message Sent to Network Server \r\n");
if (MBED_CONF_LORA_DUTY_CYCLE_ON) {
send_message();
}
break;
case TX_TIMEOUT:
case TX_ERROR:
case TX_CRYPTO_ERROR:
case TX_SCHEDULING_ERROR:
printf("\r\n Transmission Error - EventCode = %d \r\n", event);
// try again
if (MBED_CONF_LORA_DUTY_CYCLE_ON) {
send_message();
}
break;
case RX_DONE:
printf("\r\n Received message from Network Server \r\n");
receive_message();
break;
case RX_TIMEOUT:
case RX_ERROR:
printf("\r\n Error in reception - Code = %d \r\n", event);
break;
case JOIN_FAILURE:
printf("\r\n OTAA Failed - Check Keys \r\n");
break;
case UPLINK_REQUIRED:
printf("\r\n Uplink required by NS \r\n");
if (MBED_CONF_LORA_DUTY_CYCLE_ON) {
send_message();
}
break;
default:
MBED_ASSERT("Unknown Event");
}
}
// EOF
This is my Arduino sketch:
#include <DHT.h>
#include <Wire.h>
// Sensor temperatura, humedad DHT11 (test).
#define DHTPIN 10
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);
// Comunicacion i2c con nodo lora.
#define SLAVE_ADDRESS 0x29
// Variables globales de sensores
float h;
float t;
void setup() {
Serial.begin(9600);
Wire.begin(SLAVE_ADDRESS);
Wire.onReceive(receiveEvent);
dht.begin();
}
void loop() {
delay(5000);
h = dht.readHumidity();
t = dht.readTemperature();
// Comprobamos si ha habido algún error en la lectura
if (isnan(h) || isnan(t)) {
Serial.println("Error obteniendo los datos del sensor DHT11");
return;
}
Serial.print("Humedad: ");
Serial.print(h);
Serial.print(" %\t");
Serial.print("Temperatura: ");
Serial.print(t);
Serial.println(" *C ");
}
// Total de bytes del arreglo de datos a transmitir: 28 bytes.
void receiveEvent(int howMany) {
Serial.println("Recibido paquete desde MDOT LoRa Node");
Wire.beginTransmission(SLAVE_ADDRESS);
Wire.write("/Humedad:");
char hum[3];
String(h).toCharArray(hum, 3);
Wire.write(hum);
Wire.write("/Temperatura:");
char temp[3];
String(t).toCharArray(temp, 3);
Wire.write(temp);
Wire.endTransmission();
}
And I leave the repo with all the code I'm currently using: https://github.com/cipiasentini/lorai2c
Here's a picture of my physical setup (I tried it with and without the 10k pullup resistors)

Related

UniversalTelegramBot doesn't work with ESP32 but it doesn't show an error. I think it's a libraries version compatibility issue,could someone help me?

I'm developing a program in Arduino Ide (v. 1.8.13) which takes brightness values and send them to ESP32 Web Server. Also, I want to add the posibility of seeing the data via Telegram. At the moment I just want to send '/start' to the Telegram bot and Arduino program answer with a welcome message. However, the bot doesn't receive my messages. I read this is a versions issue between ArduinoJson, Universal Telegram Bot, Arduino Ide and ESP32 Core version. Could someone tell me what versions work fine in ESP32? I'm getting crazy.
I add my actual code.
These are the versions I'm using: Arduino Ide:1.8.13, Arduino Json:6.18, Universal Telegram Bot:1.3.0, Wifi Client Secure:1.0, ESP32:1.04.
Thanks in advance :)
// Import required libraries
#include <WiFi.h>
#include <Wire.h>
#include <ESPAsyncWebServer.h>
#include <SPIFFS.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_TSL2561_U.h>
#include <WiFiClientSecure.h>
#include <UniversalTelegramBot.h>
#include <ArduinoJson.h>
#include <TimeAlarms.h>
#include <Time.h>
#include <TimeLib.h>
const char* ssid_STA = "XXXXXX";
const char* password_STA = "XXXXXX";
IPAddress ip(192,168,1,44);
IPAddress gateway(192,168,1,1);
IPAddress subnet(255,255,255,0);
#define BOTtoken "XXXXXX"
#define CHAT_ID "XXXXXXX"
WiFiClientSecure client;
UniversalTelegramBot bot(BOTtoken, client);
time_t fecha;
int botRequestDelay = 1000;
unsigned long lastTimeBotRan;
// Create AsyncWebServer object on port 80
AsyncWebServer server(80);
Adafruit_TSL2561_Unified tsl = Adafruit_TSL2561_Unified(TSL2561_ADDR_FLOAT, 12345);
void configureSensor(void)
{
/* You can also manually set the gain or enable auto-gain support */
// tsl.setGain(TSL2561_GAIN_1X); /* No gain ... use in bright light to avoid sensor saturation */
// tsl.setGain(TSL2561_GAIN_16X); /* 16x gain ... use in low light to boost sensitivity */
tsl.enableAutoRange(true); /* Auto-gain ... switches automatically between 1x and 16x */
/* Changing the integration time gives you better sensor resolution (402ms = 16-bit data) */
tsl.setIntegrationTime(TSL2561_INTEGRATIONTIME_13MS); /* fast but low resolution */
//tsl.setIntegrationTime(TSL2561_INTEGRATIONTIME_101MS); /* medium resolution and speed */
// tsl.setIntegrationTime(TSL2561_INTEGRATIONTIME_402MS); /* 16-bit data but slowest conversions */
/* Update these values depending on what you've set above! */
Serial.println("------------------------------------");
Serial.print ("Gain: "); Serial.println("Auto");
Serial.print ("Timing: "); Serial.println("13 ms");
Serial.println("------------------------------------");
}
String readLuz() {
/* Get a new sensor event */
sensors_event_t event;
tsl.getEvent(&event);
/* Display the results (light is measured in lux) */
Serial.print(event.light); Serial.println(" lux");
return String(event.light);
}
void Informacion(){
Serial.println("voy a enviar");
sensors_event_t event;
tsl.getEvent(&event);
//bot.sendMessage(chat_ID, "La luminosidad en tu jardín es de " ,"");
Serial.println("enviado");
}
void handleNewMessages(int numNewMessages) {
Serial.println("handleNewMessages");
Serial.println(String(numNewMessages));
for (int i = 0; i < numNewMessages; i++) {
String chat_id = String(bot.messages[i].chat_id);
Serial.println(chat_id);
if (chat_id != CHAT_ID){
bot.sendMessage(chat_id, "Unauthorized user", "");
continue;
}
//COger texto
String text = bot.messages[i].text;
Serial.println(text);
//Coger nombre
String from_name = bot.messages[i].from_name;
//if (text == "/get_info") {
//}
if (text == "/start") {
String welcome = "Bienvenida "+from_name+"\n";
welcome += "Properties.\n\n";
welcome += "/get_info : Obtener información actual del jardín\n";
bot.sendMessage(chat_id, welcome, "");
}
}
}
/**************************************************************************/
/*
Arduino setup function (automatically called at startup)
*/
/**************************************************************************/
void setup(void)
{
Serial.begin(115200);
// client.setInsecure();
/* Initialise the sensor */
//use tsl.begin() to default to Wire,
//tsl.begin(&Wire2) directs api to use Wire2, etc.
if(!tsl.begin())
{
/* There was a problem detecting the TSL2561 ... check your connections */
Serial.print("Ooops, no TSL2561 detected ... Check your wiring or I2C ADDR!");
while(1);
}
/* Display some basic information on this sensor and Setup the sensor gain and integration time */
//displaySensorDetails();
configureSensor();
///EJEMPLO SREVER
// Initialize SPIFFS
if(!SPIFFS.begin()){
Serial.println("An Error has occurred while mounting SPIFFS");
return;
}
;
// Connect to Wi-Fi
//WiFi.softAP(ssid_AP, password_AP);
WiFi.mode(WIFI_STA);
WiFi.config(ip, gateway, subnet);
WiFi.begin(ssid_STA, password_STA);
while (WiFi.status() != WL_CONNECTED) {
delay(3000);
Serial.println("Connecting to WiFi..");
}
// Print ESP32 Local IP Address
Serial.println("IP");
Serial.println(WiFi.localIP());
// Route for root / web page
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(SPIFFS, "/index.html");
});
server.on("/luz", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/plain", readLuz().c_str());
});
// Start server
server.begin();
/*
//ALARMS
//Coger la hora real al reiniciar
//fecha = now();
//Serial.print(hour(fecha)); Serial.print(minute(fecha)); Serial.print(second(fecha)); Serial.print(day(fecha)); Serial.print(month(fecha)); Serial.println(year(fecha));
//setTime(hour(fecha), minute(fecha),second(fecha), day(fecha), month(fecha),year(fecha));
setTime(12, 42, 00, 16, 6, 21);
// Crear las alarmas y configurar las funciones correspondientes a cada una
Alarm.alarmRepeat(8, 0, 0, Informacion); // Evento a las 14:00 diario
Alarm.alarmRepeat(12,43, 0, Informacion); // Evento a las 14:05 diario
Alarm.alarmRepeat(21, 0, 0, Informacion); // Evento a las 14:10 diario
*/
}
/**************************************************************************/
/*
Arduino loop function, called once 'setup' is complete (your own code
should go here)
*/
/**************************************************************************/
void loop(void){
if (millis() > lastTimeBotRan + botRequestDelay) {
Serial.println("loop");
Serial.println(bot.last_message_received);
int numNewMessages = bot.getUpdates(bot.last_message_received + 1);
while (numNewMessages) {
Serial.println("got response");
handleNewMessages(numNewMessages);
numNewMessages = bot.getUpdates(bot.last_message_received + 1);
}
lastTimeBotRan= millis();
}
// Mostrar el reloj en el monitor serial
//digitalClockDisplay();
// Esperar 1 segundo y procesar las Alarmas mientras tanto...
//Alarm.delay(1000);
}
/*
void digitalClockDisplay() {
Serial.print(hour());
printDigits(minute());
//printDigits(second());
Serial.println();
}
void printDigits(int digits) {
Serial.print(":");
if (digits < 10)
Serial.print('0');
Serial.print(digits);
}
*/
I suppose you are missing the statement
// Add root certificate for api.telegram.org
client.setCACert(TELEGRAM_CERTIFICATE_ROOT);

MAX17205(fuel gauge) Issue with COPY NV BLOCK [E904h]

from last 2 weeks I am trying to integrate an IC MAX17205 (Fuel Gauge) on arduino mega 2560. In that I am able to read and write registers but whenever I try to copy the content of Shadow RAM to Non Volatile Memory The CommStat.NVError gets High and Without that I cant modify PackCfg reg & get the voltage for 3S cell Configuration. Please Help me in this. I have provided link to the datasheet and code below.
MAX17205 Datasheet
max17205.ino
/**
This is an example demonstrating the use of the max1720x library
Print out the information to serial monitor at 115200 baud
*/
#include <Wire.h>
#include <max1720x.h>
max1720x gauge;
void setup()
{
Serial.begin(9600); // Initializes serial port
// Waits for serial port to connect. Needed for Leonardo only
while ( !Serial ) ;
gauge.reset(); // Resets MAX1720x
delay(200); // Waits for the initial measurements to be made
}
void loop()
{
// gauge.reset();
if (gauge.getAvgCurrent() != 0) {
Serial.println(gauge.getAvgCurrent());
Wire.beginTransmission(MAX1720X_ADDR);
Wire.write(MAX1720X_COMMAND_ADDR);
Wire.write(0x04);
Wire.write(0xE9);
// delay(500);
Wire.endTransmission();
delay(400);
}
else{
Serial.print("Capacity: ");
Serial.print(gauge.getCapacity()); // Gets the battery's state of charge
Serial.print(" mAh, TTE: ");
Serial.print(gauge.getTTE()); // Gets the battery's state of charge
Serial.print(" s, TTF: ");
Serial.print(gauge.getTTF()); // Gets the battery's state of charge
Serial.print(" s, Current: ");
Serial.print(gauge.getCurrent()); // Gets the battery's state of charge
Serial.print(" mA, Temperature: ");
Serial.print(gauge.getAvgCurrent()); // Gets the battery's state of charge
Serial.print(" mA, Temperature: ");
Serial.print(gauge.getTemperature()); // Gets the battery's state of charge
Serial.print(" degC, SOC: ");
Serial.print(gauge.getSOC()); // Gets the battery's state of charge
Serial.print("%, VCELL: ");
Serial.print(gauge.getVoltage()); // Gets the battery voltage
Serial.println('mV');
delay(2000);
}
}
MAX17205.c
/**
* Name: max1720x
* Author: Luka Mustafa - Institute IRNAS Race { info#irnas.eu }
* Version: 1.0
* Description: A library for interfacing the MAXIM MAX17201/MAX17205
* Li+ fuel gauges.
* Source: https://github.com/pAIgn10/max1720x
* License: Copyright (c) 2017 Nick Lamprianidis
* This library is licensed under the GPL license
* http://www.opensource.org/licenses/mit-license.php
* Inspiration: The library is inspired by: https://github.com/pAIgn10/max1720x
* Filename: max1720x.cpp
* File description: Definitions and methods for the max1720x library
*/
#include "max1720x.h"
// Initializes variables and the Wire library
max1720x::max1720x() {
Wire.begin();
}
// Returns a measurement of the voltage of the connected LiIon Polymer battery
double max1720x::getVoltage()
{
Wire.beginTransmission(MAX1720X_ADDR);
Wire.write(MAX1720X_VBAT_ADDR);
Wire.endTransmission(false);
Wire.requestFrom(MAX1720X_ADDR, (int)2,HIGH); //send stop
uint16_t combined = Wire.read()|(Wire.read()<<8); // LSB or-ed with MSB
double voltage = combined; //combine registers
return voltage*0.078125; // //calculate actual value and return in mV
}
double max1720x::getCurrent()
{
Wire.beginTransmission(MAX1720X_ADDR);
Wire.write(MAX1720X_CURENT_ADDR);
Wire.endTransmission(false);
Wire.requestFrom(MAX1720X_ADDR, (int)2,HIGH); //send stop
int16_t combined = Wire.read()|(Wire.read()<<8); // LSB or-ed with MSB
double current = (double)combined*0.0015625/0.01;
return current;//calculate actual value as 0.0015625 mV/Ohm
}
double max1720x::getAvgCurrent()
{
Wire.beginTransmission(MAX1720X_ADDR);
Wire.write(0x61);
Wire.endTransmission(false);
Wire.requestFrom(MAX1720X_ADDR, (int)2,HIGH); //send stop
int16_t combined = Wire.read()|(Wire.read()<<8); // LSB or-ed with MSB
double current = (double)combined*0.0015625/0.01;
return combined;//calculate actual value as 0.0015625 mV/Ohm
}
double max1720x::getTemperature()
{
Wire.beginTransmission(MAX1720X_ADDR);
Wire.write(MAX1720X_TEMP_ADDR);
Wire.endTransmission(false);
Wire.requestFrom(MAX1720X_ADDR, (int)2,HIGH); //send stop
int16_t combined = Wire.read()|(Wire.read()<<8); // LSB or-ed with MSB
double temperature = (double)combined/256;
return temperature;
}
// Returns the relative state of charge of the connected LiIon Polymer battery
// as a percentage of the full capacity w/ resolution 1/256%
double max1720x::getSOC()
{
Wire.beginTransmission(MAX1720X_ADDR);
Wire.write(MAX1720X_REPSOC_ADDR);
Wire.endTransmission(false);
Wire.requestFrom(MAX1720X_ADDR, (int)2);
uint16_t combined = Wire.read()|(Wire.read()<<8); // LSB or-ed with MSB
double soc = combined; //combine registers
return soc/256; //calculate actual value and return in %
}
// RepCap or reported capacity is a filtered version of the AvCap register that prevents large jumps in the reported value caused by changes in the application such as abrupt changes in temperature or load current.
double max1720x::getCapacity()
{
Wire.beginTransmission(MAX1720X_ADDR);
Wire.write(MAX1720X_REPCAP_ADDR);
Wire.endTransmission(false);
Wire.requestFrom(MAX1720X_ADDR, (int)2);
uint16_t combined = Wire.read()|(Wire.read()<<8); // LSB or-ed with MSB
double capacity = (double)combined*0.005/0.01;
return capacity;//calculate actual value as 0.005 mVh/Ohm
}
// The TTE register holds the estimated time to empty for the application under present temperature and load conditions
double max1720x::getTTE()
{
Wire.beginTransmission(MAX1720X_ADDR);
Wire.write(MAX1720X_TTE_ADDR);
Wire.endTransmission(false);
Wire.requestFrom(MAX1720X_ADDR, (int)2);
uint16_t combined = Wire.read()|(Wire.read()<<8); // LSB or-ed with MSB
double capacity = (double)combined*5.625;
return capacity;//calculate actual value as value*5.625s
}
// The TTF register holds the estimated time to full for the application under present conditions.
double max1720x::getTTF()
{
Wire.beginTransmission(MAX1720X_ADDR);
Wire.write(MAX1720X_TTF_ADDR);
Wire.endTransmission(false);
Wire.requestFrom(MAX1720X_ADDR, (int)2);
uint16_t combined = Wire.read()|(Wire.read()<<8); // LSB or-ed with MSB
double capacity = (double)combined*5.625;
return capacity;//calculate actual value as value*5.625s
}
// Status Register (000h) The Status register maintains all flags related to alert thresholds and battery insertion or removal.
uint16_t max1720x::getStatus()
{
Wire.beginTransmission(MAX1720X_ADDR);
Wire.write(MAX1720X_STATUS_ADDR);
Wire.endTransmission(false);
Wire.requestFrom(MAX1720X_ADDR, (int)2);
uint16_t combined = Wire.read()|(Wire.read()<<8); // LSB or-ed with MSB
return combined;
}
// Reset procedure
uint8_t max1720x::reset()
{
Wire.beginTransmission(MAX1720X_ADDR);
Wire.write(MAX1720X_COMMAND_ADDR);
Wire.write(0x0f);
Wire.write(0x00);
Wire.endTransmission();
delay(50);
Wire.beginTransmission(MAX1720X_ADDR);
Wire.write(MAX1720X_CONFIG2_ADDR);
Wire.write(0x01);
Wire.write(0x00);
delay(50);
Wire.beginTransmission(MAX1720X_ADDR);
Wire.write(MAX1720X_nPackcfg);
Wire.write(0x03);
Wire.write(0x0A);
Wire.endTransmission();
delay(50);
Wire.beginTransmission(MAX1720X_ADDR);
Wire.write(0x61);
Wire.write(0x00);
Wire.write(0x00);
Wire.endTransmission();
delay(50);
Wire.beginTransmission(MAX1720X_ADDR);
Wire.write(MAX1720X_COMMAND_ADDR);
Wire.write(0xE0);
Wire.write(0x01);
Wire.endTransmission();
delay(400);
return;
}
MAX17205.h
/**
* Name: max1720x
* Author: Luka Mustafa - Institute IRNAS Race { info#irnas.eu }
* Version: 1.0
* Description: A library for interfacing the MAXIM MAX17201/MAX17205
* Li+ fuel gauges.
* Source: https://github.com/pAIgn10/LiFuelGauge
* License: Copyright (c) 2017 Nick Lamprianidis
* This library is licensed under the GPL license
* http://www.opensource.org/licenses/mit-license.php
* Inspiration: The library is inspired by: https://github.com/pAIgn10/LiFuelGauge
* Filename: max1720x.h
* File description: Definitions and methods for the max1720x library
*/
#ifndef max1720x
#define max1720x_h
#include <Arduino.h>
#include <Wire.h>
// MAX1720X register addresses
const int MAX1720X_ADDR = 0x36;
const int MAX1720X_STATUS_ADDR = 0x00; // Contains alert status and chip status
const int MAX1720X_VCELL_ADDR = 0x09; // Lowest cell voltage of a pack, or the cell voltage for a single cell
const int MAX1720X_REPSOC_ADDR = 0x06; // Reported state of charge
const int MAX1720X_REPCAP_ADDR = 0x05; // Reported remaining capacity
const int MAX1720X_TEMP_ADDR = 0x08; // Temperature
const int MAX1720X_CURENT_ADDR = 0x0A; // Battery current
const int MAX1720X_AVG_CURENT_ADDR = 0x29; // Battery current
const int MAX1720X_TTE_ADDR = 0x11; // Time to empty
const int MAX1720X_TTF_ADDR = 0x20; // Time to full
const int MAX1720X_CAPACITY_ADDR = 0x10; // Full capacity estimation
const int MAX1720X_VBAT_ADDR = 0xDA; // Battery pack voltage
const int MAX1720X_AVCELL_ADDR = 0x17; // Battery cycles
const int MAX1720X_COMMAND_ADDR = 0x60; // Command register
const int MAX1720X_CONFIG2_ADDR = 0xbb; // Command register
const int MAX1720X_nPackcfg = 0xBD;
const int MAX1720X_WriteSlave = 0x6C;
// Class for interfacing the MAX1720X Li+ fuel gauges
class max1720x
{
public:
max1720x();
double getVoltage();
double getSOC();
double getTemperature();
double getCurrent();
double getAvgCurrent();
double getCapacity();
double getTTE();
double getTTF();
uint8_t reset();
private:
uint16_t getStatus();
};
#endif // max1720x
In case it may help someone (i got here via google search):
I've been struggling with that procedure too, but got it working now.
This is my first I2C experience ever, so i think there's a lot of space for improving my code.
For me it's working like that:
const int MAX1720x_nV = 0x0b; // shifted 0x16
int a = 0; // to repeat NVCopy in case of failure
// Full Reset procedure
uint8_t max1720x::reset()
{
Wire.beginTransmission(MAX1720X_ADDR);
Wire.write(MAX1720X_COMMAND_ADDR); // Hardware reset
Wire.write(0x0f);
Wire.write(0x00);
Wire.endTransmission(true);
delay(50);
Wire.beginTransmission(MAX1720X_ADDR);
Wire.write(MAX1720X_CONFIG2_ADDR); // Fuel Gauge reset
Wire.write(0x01);
Wire.write(0x00);
return Wire.endTransmission(true); // delay(at least 10) after this function
}
// copy the shadow RAM to the nonvolatile Block
void max1720x::copyNV()
{
Wire.beginTransmission(MAX1720x_nV);
Wire.write(0x8e); // nODSCTh
Wire.write(0x00); // 16 bit Value to write there
Wire.write(0x00); // continued
Wire.endTransmission(false);
Wire.beginTransmission(MAX1720x_nV);
Wire.write(0x8f); // nODSCCfg
Wire.write(0x00); // 16 bit Value to write there
Wire.write(0x00); // continued
Wire.endTransmission(false);
.
. // add more configuarations as desired
.
// start NVCopy procedure
Wire.beginTransmission(MAX1720X_ADDR);
Wire.write(0x61); // clear commstat register
Wire.write(0x00);
Wire.write(0x00);
Wire.endTransmission(true);
Wire.beginTransmission(MAX1720X_ADDR);
Wire.write(0x60); // write E904h to 60h as described in datasheet
Wire.write(0x04);
Wire.write(0xe9);
Wire.endTransmission(true);
delay(1000); // can probably be shorter
Wire.beginTransmission(MAX1720X_ADDR); // read the CommStat.NVError
Wire.write(0x61);
Wire.endTransmission(false);
Wire.requestFrom(MAX1720x_nV, (int)2, true);
uint8_t combined = Wire.read()|(Wire.read()<<8);
Wire.endTransmission(true);
Serial.println(combined); // not neccessary, just for me
Serial.println(a);
if ((combined != 0) && (a == 1)) {
Serial.println(a);
Serial.println("failed more than once");
return;
}
if ((combined != 0) && (a == 0)) {
Serial.println("failed once");
a++;
max1720x::copyNV();
}
else if (combined == 0) { // if NVError is empty, finish the routine
Serial.println("CopyNV success!");
delay(500);
max1720x::reset(); // initiate a full reset
delay(150);
Wire.beginTransmission(MAX1720X_ADDR);
Wire.write(0xba); // probably not neccessary
Wire.write(0x00); // something with hibernate mode?
Wire.write(0x00);
Wire.endTransmission(true);
Wire.beginTransmission(MAX1720X_ADDR);
Wire.write(MAX1720X_COMMAND_ADDR);
Wire.write(0x80); // probably not neccessary
Wire.write(0x00); // something with hibernate mode?
Wire.endTransmission(true);
max1720x::reset(); // initiate a full reset, probably not neccessary
delay(500);
return;
}
}

ESP8266 random Soft WDT resets

I use WeMos D1 mini Pro with Bosche BME680 sensor shield. I get the data from sensor and put them frequently into Firebase database. Everything works, except that my device has random crashes.
The sensor library works in a way that for around 5 first minutes it is not showing IAQ data (it's returning iaq = 25 and accuracy = 0). ESP8266 crashes around 5th minute of working program - when IAQ data is available and some of correct reading had been made.
I think problem might be caused by bsec_iot_loop() which is working too long. I was trying to use yield() in random places of bsec_iot_loop(), but it didn't work. Program works perfectly, when I comment out Firebase set methods.
Huge part of my code is based on official Bosch documentation. Frankly speaking, it's extended copy-paste. Here's the docs: https://www.bosch-sensortec.com/bst/products/all_products/bsec
Here's the code:
/**********************************************************************************************************************/
/* header files */
/**********************************************************************************************************************/
#include "bsec_integration.h"
#include <Wire.h>
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <FirebaseArduino.h>
#include <time.h>
#define DEVICE_NAME "device1"
#define SSID "ssid"
#define PWD "pass"
#define FIREBASE_HOST "host"
#define FIREBASE_AUTH "auth"
#define UPDATE_INTERVAL 20
int startupTime;
/**********************************************************************************************************************/
/* functions */
/**********************************************************************************************************************/
/*!
* #brief Write operation in either Wire or SPI
*
* param[in] dev_addr Wire or SPI device address
* param[in] reg_addr register address
* param[in] reg_data_ptr pointer to the data to be written
* param[in] data_len number of bytes to be written
*
* #return result of the bus communication function
*/
int8_t bus_write(uint8_t dev_addr, uint8_t reg_addr, uint8_t *reg_data_ptr, uint16_t data_len)
{
Wire.beginTransmission((uint8_t) 0x77);
Wire.write(reg_addr); /* Set register address to start writing to */
/* Write the data */
for (int index = 0; index < data_len; index++) {
Wire.write(reg_data_ptr[index]);
}
return (int8_t)Wire.endTransmission();
}
/*!
* #brief Read operation in either Wire or SPI
*
* param[in] dev_addr Wire or SPI device address
* param[in] reg_addr register address
* param[out] reg_data_ptr pointer to the memory to be used to store the read data
* param[in] data_len number of bytes to be read
*
* #return result of the bus communication function
*/
int8_t bus_read(uint8_t dev_addr, uint8_t reg_addr, uint8_t *reg_data_ptr, uint16_t data_len)
{
int8_t comResult = 0;
Wire.beginTransmission((uint8_t) 0x77);
Wire.write(reg_addr); /* Set register address to start reading from */
comResult = Wire.endTransmission();
delayMicroseconds(150); /* Precautionary response delay */
Wire.requestFrom((uint8_t) 0x77, (uint8_t)data_len); /* Request data */
int index = 0;
while (Wire.available()) /* The slave device may send less than requested (burst read) */
{
reg_data_ptr[index] = Wire.read();
index++;
}
return comResult;
}
/*!
* #brief System specific implementation of sleep function
*
* #param[in] t_ms time in milliseconds
*
* #return none
*/
void sleep(uint32_t t_ms)
{
delay(t_ms);
}
/*!
* #brief Capture the system time in microseconds
*
* #return system_current_time current system timestamp in microseconds
*/
int64_t get_timestamp_us()
{
return (int64_t) millis() * 1000;
}
/*!
* #brief Load previous library state from non-volatile memory
*
* #param[in,out] state_buffer buffer to hold the loaded state string
* #param[in] n_buffer size of the allocated state buffer
*
* #return number of bytes copied to state_buffer
*/
uint32_t state_load(uint8_t *state_buffer, uint32_t n_buffer)
{
// ...
// Load a previous library state from non-volatile memory, if available.
//
// Return zero if loading was unsuccessful or no state was available,
// otherwise return length of loaded state string.
// ...
return 0;
}
/*!
* #brief Save library state to non-volatile memory
*
* #param[in] state_buffer buffer holding the state to be stored
* #param[in] length length of the state string to be stored
*
* #return none
*/
void state_save(const uint8_t *state_buffer, uint32_t length)
{
// ...
// Save the string some form of non-volatile memory, if possible.
// ...
}
/*!
* #brief Load library config from non-volatile memory
*
* #param[in,out] config_buffer buffer to hold the loaded state string
* #param[in] n_buffer size of the allocated state buffer
*
* #return number of bytes copied to config_buffer
*/
uint32_t config_load(uint8_t *config_buffer, uint32_t n_buffer)
{
// ...
// Load a library config from non-volatile memory, if available.
//
// Return zero if loading was unsuccessful or no config was available,
// otherwise return length of loaded config string.
// ...
return 0;
}
void connectToWiFi() {
Serial.print("Connecting to ");
Serial.println(SSID);
WiFi.begin(SSID, PWD);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
void configureFirebase() {
Serial.print("Connecting to ");
Serial.println(FIREBASE_HOST);
Serial.println("");
Firebase.begin(FIREBASE_HOST, FIREBASE_AUTH);
delay(500);
}
void configureTime() {
configTime(0, 0, "pool.ntp.org", "time.nist.gov");
Serial.println("\nWaiting for time");
while (!time(nullptr)) {
Serial.print(".");
delay(1000);
}
Serial.println("");
}
void configureSensor() {
return_values_init ret;
/* Init I2C and serial communication */
Wire.begin();
/* Call to the function which initializes the BSEC library
* Switch on low-power mode and provide no temperature offset */
ret = bsec_iot_init(BSEC_SAMPLE_RATE_LP, 5.0f, bus_write, bus_read, sleep, state_load, config_load);
if (ret.bme680_status)
{
/* Could not intialize BME680 */
Serial.println("Error while initializing BME680");
return;
}
else if (ret.bsec_status)
{
/* Could not intialize BSEC library */
Serial.println("Error while initializing BSEC library");
return;
}
Serial.println("Sensor success");
}
/*!
* #brief Handling of the ready outputs
*
* #param[in] timestamp time in nanoseconds
* #param[in] iaq IAQ signal
* #param[in] iaq_accuracy accuracy of IAQ signal
* #param[in] temperature temperature signal
* #param[in] humidity humidity signal
* #param[in] pressure pressure signal
* #param[in] raw_temperature raw temperature signal
* #param[in] raw_humidity raw humidity signal
* #param[in] gas raw gas sensor signal
* #param[in] bsec_status value returned by the bsec_do_steps() call
*
* #return none
*/
void output_ready(int64_t timestamp, float iaq, uint8_t iaq_accuracy, float temperature, float humidity,
float pressure, float raw_temperature, float raw_humidity, float gas, bsec_library_return_t bsec_status)
{
yield();
char startupTimeStr[32];
itoa(startupTime, startupTimeStr, 10);
//Get current time
time_t now = time(nullptr);
//Get last update time
int lastUpdate = Firebase.getInt("device1/lastUpdate");
if (Firebase.failed()) {
Serial.print("getting device1/lastUpdate failed:");
Serial.println(Firebase.error());
return;
}
if (lastUpdate + UPDATE_INTERVAL <= (int) now) {
//Set last update
Firebase.setInt("device1/lastUpdate", (int) now);
//Set the reading
char nowStr[32];
itoa(now, nowStr, 10);
String path = "device1/readings/" + String(nowStr);
// Firebase.setInt(path + "/iaq", iaq);
// Firebase.setFloat(path + "/temp", temperature);
// Firebase.setFloat(path + "/humid", humidity);
// Firebase.setFloat(path + "/press", pressure);
//Set uptime
int uptime = (int) now - startupTime;
//Firebase.setInt("device1/uptimes/" + String(startupTimeStr), uptime);
//Verbose data
Serial.print("Updated: ");
Serial.print((int) now);
Serial.print(" | Uptime: ");
Serial.print(uptime);
Serial.print(" | IAQ: ");
Serial.print(iaq);
Serial.print(" | Acc: ");
Serial.println(iaq_accuracy);
}
}
void setup()
{
Serial.begin(9600);
while (!Serial);
connectToWiFi();
configureFirebase();
configureTime();
configureSensor();
startupTime = (int) time(nullptr);
Serial.print("Startup time:");
Serial.println(startupTime);
/* Call to endless loop function which reads and processes data based on sensor settings */
/* State is saved every 10.000 samples, which means every 10.000 * 3 secs = 500 minutes */
bsec_iot_loop(sleep, get_timestamp_us, output_ready, state_save, 10000);
}
void loop()
{
}
And here's beginning of typical Serial monitor dump:
Soft WDT reset
ctx: cont
sp: 3fff0df0 end: 40101b51 offset: 01b0
>>>stack>>>
3fff0fa0: 3fff31f4 3fff70ec 3fff662c 3fff372c
3fff0fb0: 0002d5a7 3fff70ec 3fff662c 40208866
3fff0fc0: 3fff662c 00000000 3fff703c 40201952
3fff0fd0: 3fff703c 00001388 3fff3b04 3fff0680
3fff0fe0: 000001bb 3fff662c 3fff31f4 3fff0680
3fff0ff0: 000001bb 3fff662c 3fff31f4 402089fd
3fff1000: 3ffe9770 5561c923 3ffe9770 5561c923
3fff1010: 3fff367c 00000000 3fff3684 4020717c
3fff1020: 00000000 00000206 00000206 4020526c
3fff1030: fffffff4 00000000 3fff3684 40207980
3fff1040: 3ffe9584 00000046 3ffe96a9 40201ff3
3fff1050: 3fff36fc 3fff10c0 3fff367c 4020204c
3fff1060: 3fff3708 00000000 00000000 3ffe96a6
3fff1070: 3fff367c 3fff10a0 3ffe96a6 3ffe96a6
3fff1080: 3fff367c 3fff0680 3fff1188 402030fa
3fff1090: 3fff0660 3fff0680 3fff1188 40203b71
3fff10a0: 3fff3708 3e9b1316 3e9b1316 3d003b33
3fff10b0: 41ad99fb bf64685f 00000000 40212b8c
3fff10c0: 3fff39d0 af3cd700 0000d700 00000012
3fff10d0: 00000000 3fff11ac 3fff1198 3fff065c
3fff10e0: 3fff1128 3fff1128 402030e4 40202032
3fff10f0: 3fff112c 40590000 3ed1ca3e 3fff0660
3fff1100: 3fff11ac 3fff1120 3fff1188 40203e0a
3fff1110: 3fff1120 40fb6e3e 3fff2180 40219384
3fff1120: 3fff367c 3fff3944 3fff0680 41ad99fb
I am almost sure that this is happening because your code never reaches the loop() function, on ESP8266 Arduino library it resets the watchdog timer each interaction of loop function.
I think you can solve your problem by two ways, one is opening the function bsec_iot_loop() and put the calls inside the while(1) to loop() function, the other option is to call ESP.wdtFeed() inside the while(1) to reset watchdog Timer.
The link bellow has a good explanation about watchdog timer on ESP Arduino library.
https://techtutorialsx.com/2017/01/21/esp8266-watchdog-functions/
Okay, so I solved the problem. As I suspected there was a problem with watchdog timer. Specifically, the code never reach loop() function, because while(1) inside bsec_iot_loop(). Solution is simple. I put code inside while(1) into loop(). The rest of the code bsec_iot_loop() was declaration of variables and I made them global.
Not releasing system resources is a common problem in the arduino library. Especially on systems with a single core CPU like esp8266 where no native threading is available to the system. The underlying RTOS needs processing time to maintain its TCP-Stack and other stuff. Calling yield() every now and then is not a reliable solution.
The arduino standard library for the esp8266 mostly consists of blocking functions, which often leads the programmer into WDT-Pitfalls.
I always recommend people to use async libraries for the esp8266. There are plenty of them available. And always return control back to the operating system as much as possible because even simple delay()-Calls are capable of triggering WDT-Reset.

the IF command cant continue to else for turn off motor dc

I’ve a project for control a robot in arduino via android.
the trouble is when I press a button for pin 6 (Maju), its turn ON.
But when I press it again its always ON, cant turn OFF.
Here's my code:
int kananMaju;
int kiriMundur;
int kananMundur;
int kiriMaju;
#define Kanan A4
#define Kiri 13
#define Maju 6
#define Mundur A5
#define STBY 12
#define PWMA 11 //left
#define PWMB 10 //right
#define AIN2 8
#define AIN1 7
#define BIN1 3
#define BIN2 2
#include <SoftwareSerial.h>
#define DEBUG true
SoftwareSerial esp8266(4,5); // make RX Arduino line is pin 2, make TX Arduino line is pin 3.
// This means that you need to connect the TX line from the esp to the Arduino's pin 2
// and the RX line from the esp to the Arduino's pin 3
void setup()
{
Serial.begin(9600);
esp8266.begin(9600); // your esp's baud rate might be different
pinMode(STBY,OUTPUT);
pinMode(BIN2,OUTPUT);
pinMode(BIN1,OUTPUT);
pinMode(AIN2,OUTPUT);
pinMode(AIN1,OUTPUT);
pinMode(PWMB,OUTPUT);
pinMode(PWMA,OUTPUT);
digitalWrite(STBY, HIGH); //standby
digitalWrite(BIN1, HIGH);
digitalWrite(BIN2, HIGH);
digitalWrite(AIN1, HIGH);
digitalWrite(AIN2, HIGH);
analogWrite(PWMB, 100); //490 Hz
analogWrite(PWMA, 100); //490 Hz
pinMode(Maju,OUTPUT);
digitalWrite(Maju,LOW);
sendCommand("AT+RST\r\n",2000,DEBUG); // reset module
sendCommand("AT+CWMODE=1\r\n",1000,DEBUG); // configure as access point
sendCommand("AT+CWJAP=\"PanduGanteng\",\"akhirpekan666\"\r\n",3000,DEBUG);
delay(10000);
sendCommand("AT+CIFSR\r\n",1000,DEBUG); // get ip address
sendCommand("AT+CIPMUX=1\r\n",1000,DEBUG); // configure for multiple connections
sendCommand("AT+CIPSERVER=1,8080\r\n",1000,DEBUG); // turn on server on port 80
Serial.println("Server Ready");
}
void loop()
{
if(esp8266.available()) // check if the esp is sending a message
{
if(esp8266.find("+IPD,"))
{
delay(1000); // wait for the serial buffer to fill up (read all the serial data)
// get the connection id so that we can then disconnect
int connectionId = esp8266.read()-48; // subtract 48 because the read() function returns
// the ASCII decimal value and 0 (the first decimal number) starts at 48
esp8266.find("pin="); // advance cursor to "pin="
int pinNumber = (esp8266.read()-48); // get first number i.e. if the pin 13 then the 1st number is 1
int secondNumber = (esp8266.read()-48);
if(secondNumber>=0 && secondNumber<=9)
{
pinNumber*=10;
pinNumber +=secondNumber; // get second number, i.e. if the pin number is 13 then the 2nd number is 3, then add to the first number
}
digitalWrite(pinNumber, !digitalRead(pinNumber)); // toggle pin
// build string that is send back to device that is requesting pin toggle
String content;
content = "Pin ";
content += pinNumber;
content += " is ";
if(digitalRead(Maju))
{
content += "ON";
kiriMaju;{
digitalWrite(STBY,HIGH);
analogWrite(PWMA, 100);
digitalWrite(AIN1,HIGH);
digitalWrite(AIN2,LOW);
}
kananMaju;{
digitalWrite(STBY,HIGH);
analogWrite(PWMB, 100);
digitalWrite(BIN1, LOW);
digitalWrite(BIN2, HIGH);
}
}
else
{
content += "OFF";
}
sendHTTPResponse(connectionId,content);
// make close command
String closeCommand = "AT+CIPCLOSE=";
closeCommand+=connectionId; // append connection id
closeCommand+="\r\n";
sendCommand(closeCommand,1000,DEBUG); // close connection
}
}
}
/*
* Name: sendData
* Description: Function used to send data to ESP8266.
* Params: command - the data/command to send; timeout - the time to wait for a response; debug - print to Serial window?(true = yes, false = no)
* Returns: The response from the esp8266 (if there is a reponse)
*/
String sendData(String command, const int timeout, boolean debug)
{
String response = "";
int dataSize = command.length();
char data[dataSize];
command.toCharArray(data,dataSize);
esp8266.write(data,dataSize); // send the read character to the esp8266
if(debug)
{
Serial.println("\r\n====== HTTP Response From Arduino ======");
Serial.write(data,dataSize);
Serial.println("\r\n========================================");
}
long int time = millis();
while( (time+timeout) > millis())
{
while(esp8266.available())
{
// The esp has data so display its output to the serial window
char c = esp8266.read(); // read the next character.
response+=c;
}
}
if(debug)
{
Serial.print(response);
}
return response;
}
/*
* Name: sendHTTPResponse
* Description: Function that sends HTTP 200, HTML UTF-8 response
*/
void sendHTTPResponse(int connectionId, String content)
{
// build HTTP response
String httpResponse;
String httpHeader;
// HTTP Header
httpHeader = "HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=UTF-8\r\n";
httpHeader += "Content-Length: ";
httpHeader += content.length();
httpHeader += "\r\n";
httpHeader +="Connection: close\r\n\r\n";
httpResponse = httpHeader + content + " "; // There is a bug in this code: the last character of "content" is not sent, I cheated by adding this extra space
sendCIPData(connectionId,httpResponse);
}
/*
* Name: sendCIPDATA
* Description: sends a CIPSEND=<connectionId>,<data> command
*
*/
void sendCIPData(int connectionId, String data)
{
String cipSend = "AT+CIPSEND=";
cipSend += connectionId;
cipSend += ",";
cipSend +=data.length();
cipSend +="\r\n";
sendCommand(cipSend,1000,DEBUG);
sendData(data,1000,DEBUG);
}
/*
* Name: sendCommand
* Description: Function used to send data to ESP8266.
* Params: command - the data/command to send; timeout - the time to wait for a response; debug - print to Serial window?(true = yes, false = no)
* Returns: The response from the esp8266 (if there is a reponse)
*/
String sendCommand(String command, const int timeout, boolean debug)
{
String response = "";
esp8266.print(command); // send the read character to the esp8266
long int time = millis();
while( (time+timeout) > millis())
{
while(esp8266.available())
{
// The esp has data so display its output to the serial window
char c = esp8266.read(); // read the next character.
response+=c;
}
}
if(debug)
{
Serial.print(response);
}
return response;
}
I want to when I press button for pin 6 is ON, and when I press it again its OFF. But it's always turned ON, where's my fault?
Maju should be an input not an output
And you need to toggle a state
pinMode(Maju,INPUT);
static boolean function get_state()
{
static boolean previous = LOW;
static boolean state = LOW;
boolean current = digitalRead(Maju);
if (current == HIGH && current != previous) {
state = (state == LOW) ? HIGH : LOW;
}
previous = current;
return state;
}

Arduino SNES wireless receiver code questions

I am building a transmitter and receiver pair for two SNES controllers, as I don't like using long extension cords to get the controllers to reach the couch. I'm using ATmega328Ps for the AVRs, with RF24l01 wireless transceivers (using ManiacBugs RF24 library). I am using a modified snesPad library on the transmitter to poll the button states of two controllers and return them as a 32-bit unsigned long, then transmitting that to the receiver. All standard libraries, no issues there (so far).
However, on the receiver side, I have to properly respond to the latch and clock signals from the SNES, and I haven't found any stock libraries for that. For those not familiar with the SNES controllers, they are basically two 8-bit parallel to serial shift registers in series. They latch all of the button states on the rising edge of the latch signal (12 µs pulse high, normally low), drive the first bit on the falling edge of latch, and then drive each successive bit on the rising edge of clock (6 µs delay from fall of latch, normally high, 6 µs low - 6 µs high cycle).
I've decided to use an external interrupt to trigger the proper behavior for the latch pulse and each clock pulse. I'm new to programming Arduinos though, and new to C/C++ as well. Although my code will compile, I'm not certain if it will actually function as intended. If someone who has some experience with AVR's could take a look at my code and let me know if it will work, and if not, where and why, I would be very grateful!
Arduino sketch follows:
/*
Copyright (C) 2012 John Byers <jbyers2#wgu.edu>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
version 3 as published by the Free Software Foundation
*/
/**
* Dual Wireless Retro Controller Adapter Transmitter
*
* This is the reciever side code for the adapter set.
*/
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <RF24_config.h>
//
// Hardware Configuration
//
RF24 radio(9,10);
//
// Variable Inits
//
volatile unsigned long state2 = 0xFFFFFFFF;
volatile byte i = 0;
const uint64_t pipes[2] = { 0xF0F0F0F0E1LL, 0xF0F0F0F0D2LL };
int strobe = 2;
int clock = 3;
volatile int data1 = 5;
volatile int data2 = 6;
bool firstLoop = true;
volatile int status2 = 1;
void setup()
{
radio.begin();
radio.setRetries(0,15);
radio.enableDynamicPayloads();
Serial.begin(57600);
pinMode(strobe, INPUT);
pinMode(clock, INPUT);
pinMode(data1, OUTPUT); digitalWrite(data1, LOW);
pinMode(data2, OUTPUT); digitalWrite(data2, LOW);
radio.openWritingPipe(pipes[1]);
radio.openReadingPipe(1,pipes[0]);
//
//Dump the configuration of the RF unit for debugging
//
radio.printDetails();
//
//Setup Interupts
//
attachInterrupt(strobe,latch,RISING);
attachInterrupt(clock,data,RISING);
}
void loop()
{
if (firstLoop) {
int status1 = 1;
bool ok = radio.write( &status1, sizeof(int));
firstLoop = false;
radio.startListening();
if (!ok) {
Serial.println("sync packet transmission failed");
}
else {
Serial.println("sync packet transmission successful");
}
}
if ( radio.available() )
{
unsigned long state = 0;
radio.read( &state, sizeof(unsigned long) );
Serial.println(state, BIN);
state2 = state;
}
else
{
Serial.println("No data recieved yet");
}
}
//Latch interrupt routine
void latch()
{
i = 0;
digitalWrite(data1,HIGH);
digitalWrite(data2,HIGH);
digitalWrite(data1,bitRead(state2,i));
digitalWrite(data2,bitRead(state2,(i+16)));
Serial.println("Bit0 out");
}
//Data interrupt routine
void data()
{
i++;
digitalWrite(data1,bitRead(state2,i));
digitalWrite(data2,bitRead(state2,(i+16)));
Serial.print("Bit");
Serial.print(i);
Serial.println(" out");
if(i=15)
{
digitalWrite(data1,LOW);
digitalWrite(data2,LOW);
radio.stopListening();
int status1 = status2;
bool ok = radio.write( &status1, sizeof(int));
if (!ok) {
Serial.println("sync packet transmission failed");
}
else {
Serial.println("sync packet transmission successful");
}
radio.startListening();
}
}

Resources