I am trying to get the Qwiic Real Time Clock Module by Sparkfun working. I am using an esp8266. The clock works fine with the standard I2C pinouts, but when I change it with Wire.begin(2, 3);, it suddenly doesn't work anymore.
I've tried changing the pinouts to other examples (Wire.begin(0, 1); etc.) but nothing semes to work. I checked the wiring a ton of times and I think it is correct.
As code, I am just using a modified example written by Sparkfun.
This is my code:
void setup() {
Wire.begin(2 , 3);
Serial.begin(9600);
Serial.println("Read Time from RTC Example");
while(1) {
if (rtc.begin() == false) {
Serial.println("Something went wrong, check wiring");
} else
break;
delay(1000);
}
if (rtc.setToCompilerTime() == false) {
Serial.println("Something went wrong setting the time");
}
Serial.println("RTC online!");
}
void loop() { }
When i run the Program, it just stays in the while loop and never progresses further.
Related
I am very new to Arduino and this is my very first topic here. I am currently working on car's CAN BUS (500,000bps) communication in order to read and translate the CAN message real time. The UNO together with MCP2515 are connected to the car OBD2 port in order to sniff all supported PID data and the available output are now printed out and it looks promising enough (attached picture). However, I experienced frequent data loss, even though there is the delay of 5 seconds to read the next loop of data. I did try searching but never get any closer to the proper solution. Is this situation is called either Race Condition or data overflow? or I have to take a look at buffer size of transmitted data?
All source file and sketch are referred to https://github.com/sandeepmistry/arduino-OBD2.
Here is the sketch I used (libraries\OBD2-0.0.1\examples\OBD2_01_SupportedPIDs);
Please see the result of printout attached.
[#include <CAN.h> // the OBD2 library depends on the CAN library
#include <OBD2.h>
void setup() {
Serial.begin(9600);
while (!Serial);
Serial.println(F("OBD2 data printer"));
while (true) {
Serial.print(F("Attempting to connect to OBD2 CAN bus ... "));
if (!OBD2.begin()) {
Serial.println(F("failed!"));
delay(1000);
} else {
Serial.println(F("success"));
break;
}
}
Serial.println();
Serial.print("VIN = ");
Serial.println(OBD2.vinRead());
Serial.print("ECU Name = ");
Serial.println(OBD2.ecuNameRead());
Serial.println();
}
void loop() {
// loop through PIDs 0 to 95, reading and printing the values
for (int pid = 0; pid < 96; pid++) {
processPid(pid);
}
Serial.println();
// wait 5 seconds before next run
delay(5000);
}
void processPid(int pid) {
if (!OBD2.pidSupported(pid)) {
// PID not supported, continue to next one ...
return;
}
// print PID name
Serial.print(OBD2.pidName(pid));
Serial.print(F(" = "));
if (OBD2.pidValueRaw(pid)) {
// read the raw PID value
unsigned long pidRawValue = OBD2.pidReadRaw(pid);
Serial.print(F("0x"));
Serial.print(pidRawValue, HEX);
} else {
// read the PID value
float pidValue = OBD2.pidRead(pid);
if (isnan(pidValue)) {
Serial.print("error");
} else {
// print value with units
Serial.print(pidValue);
Serial.print(F(" "));
Serial.print(OBD2.pidUnits(pid));
}
}
Serial.println();
}][1]
Printout of sketch OBD2_03_DataPrinter.ino
Upgrading from a UNO to a Mega2560 solved my problems. Now my sketches upload much faster and the frequent crashes have disappeared. Clearly, the UNO has insufficient memory to cope with a can-bus shield.
I have an application on to control ESP32 Light Dimmer from the temperature read from a temperature sensor. The rule is very simple, when my sensor reads the temperature of more than 27ºC the lamp should be turned off by the Dimmer. However, this is not happening.
What the code does is, when the system is turned on the lamp turns on and the temperature is read from time to time, but when the temperature exceeds 27ºC the dimmer does not turn off the lamp. I think it might be something I'm doing wrong in the zero_crosss_int routine, because when the temperature reaches its limit the message "TRIAC OFF" is displayed.
Below the code used.
#define ZERO_CROSS 2
#define DIMMER_CONTROL 4
int dimming=64;
float programedTemp = 27.0;
int halfDimming=128;
int maxDimming=64;
void power(void *parameters){
tempSensor.requestTemperaturesByIndex(0);
temp=tempSensor.getTempCByIndex(0);
if(temp<programedTemp){
dimming=maxDimming;
if(temp<(programedTemp-1.0)){
dimming=maxDimming;
} else if(temp<programedTemp){
dimming++;
}
} else if(temp>programedTemp+0.9){
dimming=128;
}else{
dimming=halfDimming;
}
delay(4000);
}
void zero_crosss_int() {
if(dimming>=128){
delayMicroseconds(8.333);
digitalWrite(DIMMER_CONTROL, LOW); // triac Off
Serial.println((String) "=====>>> TRIAC OFF <<<=====");
}else{
int dimtime = (65*dimming);
delayMicroseconds(dimtime); // Off cycle
digitalWrite(DIMMER_CONTROL, HIGH); // triac firing
delayMicroseconds(8.333);
digitalWrite(DIMMER_CONTROL, LOW); // triac Off
}
}
void setup() {
pinMode(DIMMER_CONTROL, OUTPUT);
pinMode(ZERO_CROSS, INPUT);
attachInterrupt(ZERO_CROSS, zero_crosss_int, RISING);
Serial.begin(115200);
xTaskCreatePinnedToCore(power,"controlDimm",10000,NULL,0,&mainsPower,0);
}
void loop() {
}
You're doing way too much in your interrupt handler. It's amazing that it isn't just crashing constantly... the only reason that's not happening is likely because you don't do anything in loop().
It's not safe to call most of the functions you're calling in the interrupt handler. Interrupt handlers need to run for as little time as possible - other interrupts may be locked out and they may interfere with the network stack and other housekeeping functions. You absolutely should not be calling delayMicroseconds() or any Serial methods in an interrupt handler, or spending any more time there than is absolutely necessary. Almost all ESP-IDF or Arduino Core functions are not safe to call from inside an interrupt handler - the interrupt handler may interrupt another call to them while they're in an inconsistent state, or may change hardware settings while they're in the middle of using that hardware.
Your code would be much better if you structured it like this:
volatile bool zero_crossing_flag = false;
void IRAM_ATTR zero_cross_int() {
zero_crossing_flag = true;
}
void loop() {
if(zero_crossing_flag) {
zero_crossing_flag = false;
if(dimming>=128){
delayMicroseconds(8.333);
digitalWrite(DIMMER_CONTROL, LOW); // triac Off
Serial.println((String) "=====>>> TRIAC OFF <<<=====");
}else{
int dimtime = (65*dimming);
delayMicroseconds(dimtime); // Off cycle
digitalWrite(DIMMER_CONTROL, HIGH); // triac firing
delayMicroseconds(8.333);
digitalWrite(DIMMER_CONTROL, LOW); // triac Off
}
}
}
The IRAM_ATTR attribute on zero_cross_int() tells the compiler that this code must always be available. If you write an interrupt handler without IRAM_ATTR it's basically luck if it executes properly.
Restructuring your code this way will probably not solve the problem you're asking about, but it will allow it to run in a stable, reproducible way, which it's unlikely to the way it's written now.
Use your ZCD input to generate an interrupt. In the ISR start a Timer which generates another interrupt within 0ms(Full power) to 10ms(completely off) of the ZCD interrupt.
I don't understand to Switch off the lamp why are you using TRIAC instead of a Relay.
I have a problem with my brand new Arduino, it seems that
no matter what I print with
Serial.println()
be it numbers, strings or anything else, I get garbage
on the Arduino serial monitor:
Not even the simplest hello world program works.
Could you help me identify the problem and solve it?
I found the solution :)
I wrote a test program and found a working baud-rate at 600.
My test program:
long baudrates[] = {600,1200,2400,4800,9600,14400,19200,28800,38400,56000,57600,115200,128000,256000};
unsigned char baudcounter = 0;
// the setup routine runs once when you press reset:
void setup() {
// initialize serial communication
Serial.begin(baudrates[baudcounter]);
}
// the loop routine runs over and over again forever:
void loop() {
Serial.println();
Serial.println(baudrates[baudcounter]);
Serial.println(" !\"#$%&'()*+,-./0123456789:;<=>?#ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~");
Serial.println();
baudcounter++;
baudcounter %= sizeof(baudrates)/sizeof(long);
delay(1000); // delay
Serial.begin(baudrates[baudcounter]); // switch baudrate
}
When I upload this script, my normal keyboard is not usable anymore and I think the right alt key is stuck in, even if I unplug the arduino the problem is still there.
The goal of this is to have a push to talk pedal for teamspeak. I was able to get around the problem using another script that passes itself as a controller but this causes other issues with games since they think I am using a controller all of a sudden.
From what I understand, this code should loop, while the pin is active, it should simulate the right alt key being pressed. When it is done it should release all key pressed by the script. It is hard to debug this since whenever I upload it I have to spend 10 minutes to be able to use my keyboard again.
Any help would be appreciated. Extra info, I am using the arduino leonardo.
#include <Keyboard.h>
void setup() {
// Initialize Button Pins
Keyboard.begin();
pinMode(9, INPUT_PULLUP);
}
void loop() {
Keyboard.releaseAll();
while (digitalRead(9) == HIGH) {
Keyboard.press(KEY_RIGHT_ALT);
delay(500);
}
delay(500);
Keyboard.releaseAll();
// wait for new window to open:
}
Note: without the actual hardware at my disposal for some tests, it is hard to know what is going wrong, so I'll try to review your code looking for possible point of failures.
According to the docs, press() functions as if a key were pressed and held down on the keyboard.
According to these other docs, INPUT_PULLUP effectively inverts the behavior of the INPUT mode, where HIGH means the sensor is off, and LOW means the sensor is on.
Therefore, a simple modification would be:
#include <Keyboard.h>
void setup() {
// Initialize Button Pins
Keyboard.begin();
pinMode(9, INPUT_PULLUP);
}
void loop() {
static bool pressed = false;
// does the pedal close the circuit with GND?
if (digitalRead(9) == HIGH) { // no
if (pressed) {
Keyboard.release(KEY_RIGHT_ALT);
pressed = false;
}
} else { // yes
if (!pressed) {
Keyboard.press(KEY_RIGHT_ALT);
pressed = true;
}
}
delay(500); // waste time
}
Does this code display the same issues?
i'm a software developer but i'm new to Arduino, and to the electronics world.
I would like to build a simple project that combined both, and really appreciate any help where to start.
final project should be Arduino with a button and a LED, when tapping the button I want run a script on my mac, then if the script finished successfully i want to turn on the LED
I already saw some tutorial about how to use buttons and LEDs so
the main thing i'm interested here is how communicate from the Arduino to the mac and vice versa. and especially how to make it run a script on my mac.
You should look into the Serial class and the examples (via File > Examples > Commmunication)
You will need to write a bit of code on the Arduino side to send data via Serial when the button is pressed (so you can trigger your script) and receive data (when the script is done) to control the LED.
Here is a rough example on the Arduino side:
const int btnPin = 12;//button pin
const int ledPin = 13;
int lastButtonState;
void setup(){
//setup pins
pinMode(btnPin,INPUT_PULLUP);
pinMode(ledPin,OUTPUT);
//setup communication
Serial.begin(9600);
}
void loop() {
int currentButtonState = digitalRead(btnPin);//read button state
if(lastButtonState != currentButtonState && currentButtonState == LOW){//if the state of the pin changed
Serial.write(currentButtonState);//send the data
lastButtonState = currentButtonState;//update the last button state
//turn on LED
digitalWrite(ledPin,HIGH);
}
}
void serialEvent(){//if any data was sent
if(Serial.available() > 0){//and there's at least 1 byte to look at
int data = Serial.read();//read the data
//do something with it if you want
//turn off the LED
digitalWrite(ledPin,LOW);
}
}
Be aware you may have different pin numbers in your setup and depending on how the button wired, you will either look for a LOW or HIGH value in the in the condition checking the currentButtonState.
In terms of the communication there are a few key elements:
Serial.begin(9600);
Starts Serial communication with baud rate 9600. You will need to match this baud rate on the other end to ensure correct communication.
Serial.write();
Will send data to the port.
serialEvent()
is predefined in Arduino and gets called when new Serial data arrives.
Note that this gets called automatically on a Arduino Uno (and other simpler boards), however this doesn't get called on other boards:
serialEvent() doesn’t work on the Leonardo, Micro, or Yún.
serialEvent() and serialEvent1() don’t work on the Arduino SAMD Boards
serialEvent(), serialEvent1()``serialEvent2(), and serialEvent3() don’t work on the Arduino Due.
On the script side, you haven't mentioned the language, but the principle is the same: you need to know the port name and baud rate to establish communication from your mac.
(You can manually call serialEvent() in loop() as a workaround. For more details see the Arduino Reference)
The port is what you used to upload the Arduino code (something like /dev/tty.usbmodem####) and in this particular case the baud rate is 9600. You should be able to test using Serial Monitor in the Arduino IDE.
Your script will be something along there lines (pseudo code)
open serial connection ( port name, baudrate = 9600 )
poll serial connection
if there is data
run the script you need
script finished executing, therefore send data back via serial connection
Be sure to checkout the Interfacing with Software to find guide on the scripting language of your choice
Update
Here's a quick example using Processing to interface with the arduino using it's Serial library. So on the Arduino side, here's a minimal sketch:
const int btnPin = 12;//button pin
const int ledPin = 13;
boolean wasPressed;
char cmd[] = "/Applications/TextEdit.app\n";
void setup(){
//setup pins
pinMode(btnPin,INPUT_PULLUP);
pinMode(ledPin,OUTPUT);
//setup communication
Serial.begin(9600);
}
void loop() {
int currentButtonState = digitalRead(btnPin);//read button state
if(!wasPressed && currentButtonState == LOW){//if the state of the pin changed
Serial.write(cmd);//send the data
wasPressed = true;//update the last button state
//turn on LED
digitalWrite(ledPin,HIGH);
}
if(currentButtonState == HIGH) wasPressed = false;
}
void serialEvent(){//if any data was sent
if(Serial.available() > 0){//and there's at least 1 byte to look at
int data = Serial.read();//read the data
//do something with it if you want
//turn off the LED
digitalWrite(ledPin,LOW);
}
}
and on the Processing side:
import processing.serial.*;
void setup(){
try{
Serial arduino = new Serial(this,"/dev/tty.usbmodemfa141",9600);
arduino.bufferUntil('\n');//buffer until a new line is encountered
}catch(Exception e){
System.err.println("Error opening serial connection! (check cables and port/baud settings!");
e.printStackTrace();
}
}
void draw(){}
void serialEvent(Serial s){
String[] command = s.readString().trim().split(",");//trim spaces, split to String[] for args
println(command);//see what we got
open(command);//run the command
s.write("A");//send a message back to flag that the command is finished (turn LED off)
}
Hope this is a helpful proof of concept. Feel free to use any other language with a serial library available instead of Processing. The syntax may differ just a tad (probably more on the running of the process/command), but the concept is the same.
Update The example above can be simplified a touch by not having the command on the Arduino side:
there's less data sent on Serial from Arduino to Processing reducing communication time and the odds of communication interference
the app runs on a computer hence changing the command is simpler to do on software side as opposed to having to change the Arduino code and re-upload each time.
Arduino:
const int btnPin = 12;//button pin
const int ledPin = 13;
boolean wasPressed;
void setup(){
//setup pins
pinMode(btnPin,INPUT_PULLUP);
pinMode(ledPin,OUTPUT);
//setup communication
Serial.begin(9600);
}
void loop() {
int currentButtonState = digitalRead(btnPin);//read button state
if(!wasPressed && currentButtonState == LOW){//if the state of the pin changed
Serial.write('R');//send the data
wasPressed = true;//update the last button state
//turn on LED
digitalWrite(ledPin,HIGH);
}
if(currentButtonState == HIGH) wasPressed = false;
}
void serialEvent(){//if any data was sent
if(Serial.available() > 0){//and there's at least 1 byte to look at
int data = Serial.read();//read the data
//do something with it if you want
//turn off the LED
digitalWrite(ledPin,LOW);
}
}
Processing:
import processing.serial.*;
String[] command = {"/Applications/TextEdit.app", "myText.txt"};
void setup() {
try {
Serial arduino = new Serial(this, "/dev/tty.usbmodemfa141", 9600);
}
catch(Exception e) {
System.err.println("Error opening serial connection! (check cables and port/baud settings!");
e.printStackTrace();
}
}
void draw() {
}
void serialEvent(Serial s) {
if (s.read() == 'R') {
launch(command);//run the command
s.write("A");//send a message back to flag that the command is finished (turn LED off)
}
}
(btw, 'R' is an arbitrary single character, can be something else as long it's the same char on both Serial send and receive sides)
Also, bare in mind launch() returns Proccess which can be useful to get more information from the software launched.
Dunno if it will help you as much as it did me but this question shows a simple example of how to use the script with a simple button in an android app
Run script with android app
Hope it helps
I found a workaround in Linux. It's a little messy but it works. I use Coolterm to capture the serial output from the arduino to a text file and I wrote a small python script that reads the file (or simply, in my case, executes the command I want if the file is not empty).