SD card error for Arduino Mega - embedded

I am trying to run a simple program using a SD card module from spark fun with a Arduino Mega2560. This is the program i am current using:
#include <SD.h>
const int chipSelect = 10;
void setup()
{
Serial.begin(9600);
Serial.print("Initializing SD card...");
pinMode(53, OUTPUT);
digitalWrite(10, HIGH);
if (!SD.begin(chipSelect)) {
Serial.println("Card failed, or not present");
// don't do anything more:
return;
}
Serial.println("card initialized.");
}
void loop()
{
String dataString = "";
for (int analogPin = 0; analogPin < 3; analogPin++) {
int sensor = analogRead(analogPin);
dataString += String(sensor);
if (analogPin < 2) {
dataString += ",";
}
}
File dataFile = SD.open("datalog.txt", FILE_WRITE);
if (dataFile) {
dataFile.println(dataString);
dataFile.close();
Serial.println(dataString);
}
else {
Serial.println("error opening datalog.txt");
}
}
The error i am receiving says :
Initializing SD card...Card failed, or not present
error opening datalog.txt

Change
pinMode(53, OUTPUT);
digitalWrite(10, HIGH);
To
pinMode(53, OUTPUT);
digitalWrite(53, HIGH);
And have a try.

Sometimes it may happen for not writing this
File dataFile = SD.open("datalog.txt", FILE_WRITE);
immediately after this [or long before writing to that file]
Serial.println("card initialized.");
Believe me, this happened to me.

Related

ESP8266 WIFI Connection lost after Acces Point reboot

Heyho,
at first, I am no programmer - it's just my hobby :)
I have a cistern in my garden and I want to measure the level of it with an ESP8266 and an ultrasonic sensor.
I am sending the data via mqtt to my mqtt broker.
Everything working well but when my accesspoint is rebooting two times a day and after that reboot the ESP8266 doesn't connect to the WIFI again.
What I've done so far:
setting the WiFi.setAutoReconnect(true); to true (find that in the Internet)
call the function setup(); in void loop() again
So, I think I have a mistake in thinking with that problem.
Heres my code:
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <Ultrasonic.h>
Ultrasonic ultrasonic(12, 13);
const char* ssid = "XXX"; // Enter your WiFi name
const char* password = "XXX"; // Enter WiFi password
const char* mqttServer = "XXX";
const int mqttPort = 1883;
const char* mqttUser = "XXX";
const char* mqttPassword = "XXX";
#define abstand_topic "home/zisterne/fuellstand"
#define abstand_topic_2 "home/zisterne/mittl_fuellstand"
const int RunningAverageCount = 24; // Anzahl der in den Laufenden-Mettelwert aufgenommenen Messungen
float RunningAverageBuffer[RunningAverageCount];
int NextRunningAverage;
unsigned long previousMillis = 0;
unsigned long interval = 30000;
WiFiClient espClient;
PubSubClient client(espClient);
void setup() {
Serial.begin(115200);
WiFi.begin(ssid, password);
WiFi.setAutoReconnect(true);
WiFi.persistent(true);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.println("Connecting to WiFi..");
}
Serial.println("Connected to the WiFi network");
client.setServer(mqttServer, mqttPort);
client.setCallback(callback);
while (!client.connected()) {
Serial.println("Connecting to MQTT...");
if (client.connect("ESP8266Client", mqttUser, mqttPassword )) {
Serial.println("connected");
} else {
Serial.print("failed with state ");
Serial.print(client.state());
delay(2000);
}
}
// //Sensor auslesen und übergeben
// int Sensor = ultrasonic.distanceRead();
// char Abstand[10];
// itoa(Sensor,Abstand,10);
//
// Serial.println(ultrasonic.distanceRead());
// client.publish(abstand_topic, Abstand);
}
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message arrived in topic: ");
Serial.println(topic);
Serial.print("Message:");
for (int i = 0; i < length; i++) {
Serial.print((char)payload[i]);
}
Serial.println();
Serial.println("-----------------------");
}
void loop() {
client.loop();
//WLAN Reconnect
if (WiFi.status() != WL_CONNECTED) {
delay(500);
setup();
}
//Sensor auslesen und übergeben
int Sensor = ultrasonic.distanceRead();
char Abstand[10];
itoa(Sensor,Abstand,10);
Serial.println(ultrasonic.distanceRead());
client.publish(abstand_topic, Abstand);
//unsigned long minutes = 1000 * 300;
float RawDistance = ultrasonic.distanceRead();
RunningAverageBuffer[NextRunningAverage++] = RawDistance;
if (NextRunningAverage >= RunningAverageCount)
{
NextRunningAverage = 0;
}
float RunningAverageDistance = 0;
for(int i=0; i< RunningAverageCount; ++i)
{
RunningAverageDistance += RunningAverageBuffer[i];
}
RunningAverageDistance /= RunningAverageCount;
int mittelwert = RunningAverageDistance;
char mittl_Abstand[10];
itoa(mittelwert,mittl_Abstand,10);
client.publish(abstand_topic_2, mittl_Abstand);
delay(5000);
yield();
}
So, now I hope someone of you can help me with my small problem! :)
Greetings,
Philipp

Arduino Sensor API Webserver

When I load this code into my Arduino, he connects with the WiFi and shows up at my IP-Scanner. But when I open the IP of the device in FireFox nothing loads. (http://10.0.0.40/env) Is there an issue with my code, or doesnt it work like this. I have a sensor which reads the temperature and humidity. These two value should be available in my network to fetch(). With Javascript I want to display these on my local html-page. The network credentials are just censored.
#include <ArduinoJson.h>
#include <WiFi.h>
#include <WebServer.h>
#include <DHT.h>
#define DHTPIN 13
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);
const char *ssid = "XXX";
const char *pwd = "XXX";
StaticJsonDocument<250> jsonDocument;
char buffer[250];
float temperature;
float humidity;
WebServer server(80);
void connectToWiFi() {
Serial.print("Connect to: ");
Serial.println(ssid);
WiFi.begin(ssid, pwd);
while (WiFi.status() !=WL_CONNECTED){
Serial.print(".");
delay(1000);
}
Serial.print("Connected. IP: ");
Serial.println(WiFi.localIP());
}
void setup_routing(){
server.on("/temperature", getTemperature);
server.on("/humidity", getHumidity);
server.on("/env", getEnv);
server.begin();
}
void create_json(char *tag, float value, char *unit){
jsonDocument.clear();
jsonDocument["type"] = tag;
jsonDocument["value"] = value;
jsonDocument["unit"] = unit;
serializeJson(jsonDocument, buffer);
}
void add_json_object(char *tag, float value, char *unit){
JsonObject obj = jsonDocument.createNestedObject();
obj["type"] = tag;
obj["value"] = value;
obj["unit"] = unit;
}
void read_sensor_data(void * parameter) {
for (;;) {
temperature = dht.readTemperature();
humidity = dht.readHumidity();
}
delay(2000);
}
void getTemperature(){
create_json("temperature", temperature,"°C");
server.send(200, "application/json", buffer);
Serial.println(temperature);
}
void getHumidity(){
create_json("humidty", humidity, "%");
server.send(200, "application/json", buffer);
Serial.println(humidity);
}
void getEnv() {
jsonDocument.clear();
add_json_object("temperature", temperature, "°C");
add_json_object("humidity", humidity, "%");
serializeJson(jsonDocument, buffer);
server.send(200, "application/json", buffer);
}
void setup() {
dht.begin();
Serial.begin(115200);
Serial.println(WiFi.localIP());
connectToWiFi();
setup_routing();
}
void loop() {
// put your main code here, to run repeatedly:
delay(2000);
float temperature = dht.readTemperature();
float humidty = dht.readHumidity();
}
The loop() code you posted looks like this:
void loop() {
// put your main code here, to run repeatedly:
delay(2000);
float temperature = dht.readTemperature();
float humidty = dht.readHumidity();
}
You didn't include the necessary code to allow the web server to run. The web server needs to be given a chance to run during the loop() or else it can't service requests.
Your loop() needs to include server.handleClient().
You can see this in basic examples showing how to use the WebServer.
Once you add that code you'll need to rewrite loop() to not always delay for two seconds or else you'll be delaying the web server as well as the sensor reads.

User input stuck in loop

I have made this code on Arduino where the objective is to have the user type in a delay time into the serial monitor, and then the LED should be blink with that delay time. For example if I type in 1000 the LED should be turned on for 1 second then off for 1 second, then repeat.
My problem is that when the code has finished running once, it waits for a new user input, instead of continuing to blink. I think i have to take the Serial.parseInt out of the loop but i'm not sure how as every time I have tried to put it somewhere else the LED just lights up constantly.
Here is the code:
int ledPin = 13;
void setup() {
// put your setup code here, to run once:
pinMode(ledPin, OUTPUT);
Serial.begin(9600);
Serial.print(" Enter delay time: ");
while (!Serial.available());
}
void loop() {
// put your main code here, to run repeatedly
int delayTime = Serial.parseInt();
digitalWrite(ledPin, HIGH);
delay(delayTime);
digitalWrite(ledPin, LOW);
delay(delayTime);
}
Serial.parseInt is a blocking function. That means it waits for valid serial input until it times out. Because of this, any other action in loop has to wait too. Reading user input in setup works only once though, so it never asks the user for input again.
To avoid this, you'll have to check the serial buffer, and then read each byte individually, while also doing the LED blinking in the main loop.
Another thing to avoid now, is the use of the delay function, because it also hangs the entire main loop (including the serial readings) for the given parameter time. You can still blink the LED by using timestamp intervals.
For a nice example of a non-blocking serial read, we can use this sample from the Arduino docs. Additionally, for another nice example of an LED-blinking sketch without using delay, we can use the BlinkWithoutDelay sample from the Arduino docs too.
String inString = "";
unsigned long previousMillis = 0;
int delayTime = 0;
int ledState = LOW;
int ledPin = 13;
void nonBlockingSerialReadDelayTime() {
while (Serial.available() > 0) {
int inChar = Serial.read();
if (isDigit(inChar)) {
// convert the incoming byte to a char and add it to the string
inString += (char)inChar;
}
// if you get a newline (user pressed ENTER on the serial console)
if (inChar == '\n') {
// set our new delay time
delayTime = inString.toInt();
// clear the string for new input
inString = "";
// ask user again
Serial.print(" Enter delay time: ");
}
}
}
void blinkLED() {
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= delayTime) {
// save the last time you blinked the LED
previousMillis = currentMillis;
// if the LED is off turn it on and vice-versa
if (ledState == LOW) {
ledState = HIGH;
} else {
ledState = LOW;
}
// set the LED with the ledState of the variable
digitalWrite(ledPin, ledState);
}
}
void setup() {
pinMode(ledPin, OUTPUT);
Serial.begin(9600);
while (!Serial.available());
Serial.print(" Enter delay time: ");
}
void loop() {
nonBlockingSerialReadDelayTime();
blinkLED();
}
Simply read the delay time in your setup befor you enter loop
int ledPin = 13;
int delayTime = 0;
void setup() {
// put your setup code here, to run once:
pinMode(ledPin, OUTPUT);
Serial.begin(9600);
Serial.print(" Enter delay time: ");
while (!Serial.available());
delayTime = Serial.parseInt();
}
void loop() {
// put your main code here, to run repeatedly
digitalWrite(ledPin, HIGH);
delay(delayTime);
digitalWrite(ledPin, LOW);
delay(delayTime);
}
Sure Serial.parseInt() is blocking, but you can combine it with Serial.available()
const int ledPin = 13;
int delayTime = 1000;
void setup() {
pinMode(ledPin, OUTPUT);
Serial.begin(9600);
Serial.print(" Enter delay time: ");
}
void loop() {
digitalWrite(ledPin, HIGH);
delay(delayTime);
digitalWrite(ledPin, LOW);
delay(delayTime);
if (Serial.available()) {
int temp = Serial.parseInt();
if (temp > 0) delayTime = temp;
Serial.print(" Enter delay time: ");
}
}
Of course this approach does not allow to break into a very slow blink cycle immediately, but that's a different issue.

How can I write code to receive whole string from a device on rs232?

I want to know how to write code which receives specific string.for example, this one OK , in this I only need "OK" string.
Another string is also like OK
I have written code in keil c51 for at89s52 microcontroller which works but I need more reliable code.
I'm using interrupt for rx data from rs232 serial.
void _esp8266_getch() interrupt 4 //UART Rx.{
if(TI){
TI=0;
xmit_bit=0;
return ;
}
else
{
count=0;
do
{
while(RI==0);
rx_buff=SBUF;
if(rx_buff==rx_data1) //rx_data1 = 0X0D /CR
{
RI=0;
while(RI==0);
rx_buff=SBUF;
if(rx_buff==rx_data2) // rx_data2 = 0x0A /LF
{
RI=0;
data_in_buffer=1;
if(loop_conti==1)
{
if(rec_bit_flag==1)
{
data_in_buffer=0;
loop_conti=0;
}
}
}
}
else
{
if(data_in_buffer==1)
{
received[count]=rx_buff; //my buffer in which storing string
rec_bit_flag=1;
count++;
loop_conti=1;
RI=0;
}
else
{
loop_conti=0;
rec_bit_flag=0;
RI=0;
}
}
}
while(loop_conti==1);
}
rx_buff=0;
}
This is one is just for reference, you need develop the logic further to your needs. Moreover, design is depends on what value is received, is there any specific pattern and many more parameter. And this is not a tested code, I tried to give my idea on design, with this disclaimer here is the sample..
//Assuming you get - "OK<CR><LF>" in which <CR><LF> indicates the end of string steam
int nCount =0;
int received[2][BUF_SIZE]; //used only 2 buffers, you can use more than 2, depending on how speed
//you receive and how fast you process it
int pingpong =0;
bool bRecFlag = FALSE;
int nNofbytes = 0;
void _esp8266_getch() interrupt 4 //UART Rx.
{
if(TI){
TI=0;
xmit_bit=0;
return ;
}
if(RI) // Rx interrupt
{
received[pingpong][nCount]=SBUF;
RI =0;
if(nCount > 0)
{
// check if you receive end of stream value
if(received[pingpong][nCount-1] == 0x0D) && (received[pingpong][nCount] == 0x0A))
{
bRecFlag = TRUE;
pingpong = (pingpong == 0);
nNofbytes = nCount;
nCount = 0;
return;
}
}
nCount++;
}
return;
}
int main()
{
// other stuff
while(1)
{
// other stuff
if(bRecFlag) //String is completely received
{
buftouse = pingpong ? 0 : 1; // when pingpong is 1, buff 0 will have last complete string
// when pingpong is 0, buff 1 will have last complete string
// copy to other buffer or do action on received[buftouse][]
bRecFlag = false;
}
// other stuff
}
}

PubSubClient & ArduinoJSON - Arduino passing char to digitalWrite

I am not sure how to pass the values in the function in order to be used within the digitalWrite functions.
I'm getting the following error:
error: cannot convert 'String' to 'uint8_t' {aka unsigned char}' for argument '1' to 'void digitalWrite(uint8_t, uint8_t)'
pubsub callback
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("New message on [");
Serial.print(topic);
Serial.print("] ");
Serial.println("");
char s[length];
for (int i = 0; i < length; i++) {
Serial.print((char)payload[i]);
s[i]=payload[i];
}
StaticJsonBuffer<500> jsonBuffer;
JsonObject& root = jsonBuffer.parseObject(s);
if (!root.success()) {
Serial.println("parseObject() failed");
}
String relay = root["relay"]; // "relayOne"
int time = root["timestamp"]; // 1351824120
String trigger = root["trigger"]; // "ON"
// Feel free to add more if statements to control more GPIOs with MQTT
commander(relay, trigger);
}
commander function
void commander(String relay, String trigger) {
if(trigger == "ON"){
Serial.print("Turning ");
Serial.println(relay);
Serial.println(" on");
digitalWrite(relay, HIGH);
} else if(trigger == "OFF"){
Serial.println(relay);
digitalWrite(relayOne, LOW);
Serial.print("TRIGGERED!");
} else {
// turn all the LEDs off:
for (int pin = 0; pin < relayPinCount; pin++) {
digitalWrite(relayPins[pin], LOW);
}
}
Serial.println();
}
void commander(String relay, String trigger) {
uint8_t pinNo;
if ( relay == "relayOne" ) {
pinNo = RELAY_1_PIN;
} else
if ( relay == "anotherRelay" ) {
pinNo = OTHER_RELAY_PIN;
} else
if ( ... ) {
...
} else {
return;
}
if(trigger == "ON"){
Serial.print("Turning ");
Serial.println(relay);
Serial.println(" on");
digitalWrite(pinNo, HIGH);
} else if(trigger == "OFF"){
Serial.println(relay);
digitalWrite(pinNo, LOW);
Serial.print("TRIGGERED!");
} else {
// turn all the LEDs off:
for (int pin = 0; pin < relayPinCount; pin++) {
digitalWrite(relayPins[pin], LOW);
}
}
Serial.println();
}