I'm having a strange problem that I hope someone can help with. My sketch works perfectly when uploaded to my UNO, but when I unplug it and plug it back in, it doesn't work correctly. If I re-upload it, it works again until power is cycled.
Once uploaded, the LCD reads:
Ferm:73.4 73/75
Room:75.1 75/75
After cycling power:
Ferm:73.45 73/18
Room:74.83 75/18
So after cycling power, I now get 2 decimal places and the "high" temp is stuck at "18".
/*
The circuit:
* 5V to Arduino 5V pin
* GND to Arduino GND pin
* CLK to Analog #5
* DAT to Analog #4
*/
// include the library code:
#include "Wire.h"
#include "Adafruit_LiquidCrystal.h"
#include <OneWire.h>
#include <DallasTemperature.h>
//variables for temp readings
float fermTemp;
float fermTempL=100;
float fermTempH=5;
float roomTemp;
float roomTempL=100;
float roomTempH=5;
// set OneWire bus to digital PIN 4 on the Arduino
#define ONE_WIRE_BUS 4
// Setup OneWire instance
OneWire oneWire(ONE_WIRE_BUS);
// Pass oneWire reference to Dallas Temp
DallasTemperature sensors(&oneWire);
// Connect via i2c, default address #0 (A0-A2 not jumpered)
Adafruit_LiquidCrystal lcd(0);
void setup()
{
// set up the LCD's number of rows and columns:
lcd.begin(16, 2);
// turn on backlight
lcd.setBacklight(HIGH);
}
void loop() {
readtemp();
LCDPrint();
}
void readtemp()
{
// get data from sensors
sensors.requestTemperatures();
fermTemp = (sensors.getTempFByIndex(0));
roomTemp = (sensors.getTempFByIndex(1));
// check/set High and Low temp
if (fermTemp<fermTempL) {
fermTempL=fermTemp;
}
if (fermTemp>fermTempH) {
fermTempH=fermTemp;
}
if (roomTemp<roomTempL) {
roomTempL=roomTemp;
}
if (roomTemp>roomTempH) {
roomTempH=roomTemp;
}
}
void LCDPrint()
{
lcd.setCursor(0,0);
lcd.print("Ferm:");
lcd.print(fermTemp,1);
lcd.setCursor(11,0);
lcd.print(fermTempL,0);
lcd.print("/");
lcd.print(fermTempH,0);
lcd.setCursor(0,1);
lcd.print("Room:");
lcd.print(roomTemp,1);
lcd.setCursor(11,1);
lcd.print(roomTempL,0);
lcd.print("/");
lcd.print(roomTempH,0);
}
I counted your characters, 16 per line. If you have a 16X2 display, there might be characters printed beyond the screen. I suspect it was not really 18, but something larger, say 180 or 1800. That could have been a result of failed first attempt to read temperature. This reading is stuck with you as temp High. In your code, you should define a reasonable high temperature, such as 125. Don't update temp High if it is above the reasonable temperature.
To confirm it, print temp High to serial port and inspect the value.
Related
I am new to Arduino and Esp32 programming. I need to connect PCA9685 controller to ESP-32 cam to be able to control multiple servo motors but the SCL and SDA pins are occupied by the UART control board.
I searched for this and found something related to Wire.h library and wire.begin() and TwoWire but unable to implement it.
#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>
// called this way, it uses the default address 0x40
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();
#define SERVOMIN 150 // This is the 'minimum' pulse length count (out of 4096)
#define SERVOMAX 600 // This is the 'maximum' pulse length count (out of 4096)
#define USMIN 600 // This is the rounded 'minimum' microsecond length based on the minimum pulse of 150
#define USMAX 2400 // This is the rounded 'maximum' microsecond length based on the maximum pulse of 600
#define SERVO_FREQ 50 // Analog servos run at ~50 Hz updates
// our servo # counter
uint8_t servonum = 0;
void setup() {
Wire.begin();
Wire.begin(2,15,100000); // this is to map new SCL and SDA pins to 2,15
Serial.begin(9600);
Serial.println("8 channel Servo test!");
pwm.begin();
pwm.setOscillatorFrequency(27000000);
pwm.setPWMFreq(SERVO_FREQ); // Analog servos run at ~50 Hz updates
delay(10);
}
// You can use this function if you'd like to set the pulse length in seconds
// e.g. setServoPulse(0, 0.001) is a ~1 millisecond pulse width. It's not precise!
void setServoPulse(uint8_t n, double pulse) {
double pulselength;
pulselength = 1000000; // 1,000,000 us per second
pulselength /= SERVO_FREQ; // Analog servos run at ~60 Hz updates
Serial.print(pulselength); Serial.println(" us per period");
pulselength /= 4096; // 12 bits of resolution
Serial.print(pulselength); Serial.println(" us per bit");
pulse *= 1000000; // convert input seconds to us
pulse /= pulselength;
Serial.println(pulse);
pwm.setPWM(n, 0, pulse);
}
void loop() {
pwm.setPWM(0, 0, 250);
}
Here is the test code that I am trying to run.
I got the implementation idea from https://randomnerdtutorials.com/esp32-i2c-communication-arduino-ide/
There are a few problems that I encounter along with no response from the code-
When PCA9685 is connected to esp32-cam and I try to upload the code, it doesn't work and gives fatal error.
When the reset button is pressed before upload the built-in flash blinks. This is presented as a problem because while trying to upload the code without PCA9685 attached, the code is uploaded without any fatal error and there is no 'flash blink'.
I tried a code from the same website mentioned above that looks for I2C devices and prints their address. It shows no devices even though the servo controller is connected to it.
PS- I am an absolute beginner in this field.
I'm currently trying to put together a datalogger with an OLED screen and am having issues when adding the SD library to the script. I've seen that others have gotten error messages when combining Oled and SD cards that is related to RAM. Though in my case, the code runs, there is no error message, but the screen doesn't display anything. The code below shows the "OLED code" where the Oled display wouldn't show anything when I added the "#include <SD.h>". Also, since I quite new to this, some constructive criticism of the code itself is also welcome
Thanks!
#include <SPI.h>
#include <SD.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include "Adafruit_MCP9808.h"
#include <Adafruit_BME280.h>
Adafruit_BME280 bme; // use I2C interface
Adafruit_Sensor *bme_temp = bme.getTemperatureSensor();
Adafruit_Sensor *bme_pressure = bme.getPressureSensor();
Adafruit_Sensor *bme_humidity = bme.getHumiditySensor();
//oled definitions
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET 4 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// Create the MCP9808 temperature sensor object
Adafruit_MCP9808 tempsensor = Adafruit_MCP9808();
void setup() {
Serial.begin(9600);
display.begin(SSD1306_SWITCHCAPVCC, 0x3D); // Address 0x3D for 128x64
// Clear the buffer
display.display();
delay(2000);
display.clearDisplay();
display.setTextSize(1);
display.setCursor(0, 0);
display.setTextColor(WHITE);
while (!Serial);
Serial.println("Loading");
if (!tempsensor.begin(0x18)) {
Serial.println("Couldn't find MCP9808! Check your connections and verify the address is correct.");
while (1);
}
Serial.println(F("Found MCP9808!"));
tempsensor.setResolution(3); // sets the resolution mode of reading, the modes are defined in the table bellow:
// Mode Resolution SampleTime
// 0 0.5°C 30 ms
// 1 0.25°C 65 ms
// 2 0.125°C 130 ms
// 3 0.0625°C 250 ms
if (!bme.begin()) {
Serial.println(F("Could not find a valid BME280 sensor, check wiring!"));
while (1) delay(10);
}
bme_temp->printSensorDetails();
bme_pressure->printSensorDetails();
bme_humidity->printSensorDetails();
}
void loop() {
float temp = bme.readTemperature(); // get temperature in degree Celsius
float humi = bme.readHumidity(); // get humidity in rH%
float pres = bme.readPressure(); // get pressure in Pa
tempsensor.wake();
//Serial.println (tempsensor.getResolution());
float c = tempsensor.readTempC();
float f = tempsensor.readTempF();
//float sensor=analogRead(A4);
display.setCursor(0, 0);
display.print(F("Temp_1: "));
display.print(c,2);display.println(" \tC ");
display.println("");
display.print(F("Temp_2: "));
display.print(temp,2);display.println(" \tC ");
display.println("");
display.print(F("Humidity: "));
display.print(humi,2);display.println(" %RH ");
display.println("");
display.print(F("Pressure: "));
display.print(pres/100,2);display.println(" kPa ");
display.display();
delay(1000);
display.clearDisplay();
Its just memory problem. I fix it by decrease the resolution only for usage area.. Its not the best solution however good enough for me
This was apparently a memory issue.
I've now connected an Arduino Mega instead of a Nano, and the code ran nicely. I've also added the remaining piece of code that was necessary to log the sensor readings.
According to what I've read on other forums, the SD and SPI libraries take up quite a lot of memory.
I have this RFID reader "Rosslare AY-X12", and it's working with Wiegand 26bit. I have an arduino mini Pro and connected together it's working fine but it only reads the card one time and then I have nothing.
When I put on the card arduino reads that card but only one time during the card is near by the reader and it again reads that card when I put off the card and then I put on. But I want to read that card continuously, I mean when the card is near by the Reader still reading the card, every 1ms reads that card.
Do you have any idea how to do that ? Is there any RFID arduino library which can do that? I had got the Mifare and its can do that. But this 125Khz reader which can communicate over Wiegand can't do that or I don't know how to do that.
I'm using this library : https://github.com/monkeyboard/Wiegand-Protocol-Library-for-Arduino
My previous answer was deleted. I am going to make another attempt to answer the questions.
Do you have any idea how to do that ?
This cannot be done by Arduino because Arduino in your case is just reading the D0 and D1 pulses from your RFID reader. Since your RFID reader Rosslare AY-X12 does not send out continuous output of wiegand protocol, there is no way Arduino can read more than what was not sent to it.
The common RFID readers will not send continuous data of the same card because in the common use case (entry/exit/attendance), normally one tap is to check-in and another tap is to check-out. If the RFID reader sends continuous data of the same card, the main system receiving the multiple wiegand data will be confused and will not be able to determine if the user actually wish to check-in or check-out.
Is there any RFID arduino library which can do that?
No. There is no such RFID Arduino library. If the RFID reader is not sending out continuous data, there is no way the receiver (Arduino) can receive them.
Is there a way to achieve this?
Yes, there are some readers that has the option to turn on the continuous output of data, for example 714-52 Mifare® ID Reader with selectable outputs. In its specification :
Continuous output with tag in field or single transmission
With this reader configured to continuous output, you can then use Arduino and the monkeyboard wiegand library to read the data.
I wrote my own wiegand code. Its not that difficult. I attached interrupts to the data pins and when they change I log the zero or one. You then build up the binary string and once timed out because no bits coming in. Then you convert the binary to decimal.
#include <LiquidCrystal.h>
int data0 = 2; //set wiegand data 0 pin
int data1 = 3; //set wiegand data 1 pin
unsigned long bit_holder; //unsigned long (positive 32 bit number)
unsigned long oldbit = 0;
volatile int bit_count = 0;
LiquidCrystal lcd(8, 9, 10, 11, 12, 13);
unsigned long badge;
unsigned int timeout;
unsigned int t = 800;
void setup() {
Serial.begin(9600);
lcd.begin(16, 2);
lcd.print("Present Badge");
delay(2);
Serial.println("Present Badge");
pinMode(data0, INPUT);
digitalWrite(data0, HIGH);
pinMode(data1, INPUT);
digitalWrite(data1, HIGH);
attachInterrupt(0, zero, FALLING); //attach interrupts and assign functions
attachInterrupt(1, one, FALLING);
}
void zero(){
bit_count ++;
bit_holder = (bit_holder << 1) + 0; //shift left one and add a 0
timeout = t;
}
void one(){
bit_count ++;
bit_holder = (bit_holder << 1) + 1; //shift left one and add a 1
timeout = t;
}
void loop() {
timeout --;
if (timeout == 0 && bit_count > 0){
lcd.clear();
lcd.print("Dec:");
lcd.print(bit_holder);
lcd.setCursor(0,1);
lcd.print("Hex:");
lcd.print(String(bit_holder,HEX));
Serial.print("bit count= ");
Serial.println(bit_count);
Serial.print("bits= ");
Serial.println(bit_holder,BIN);
oldbit = bit_holder; //store previous this value as previous
bit_count = 0; //reset bit count
bit_holder = 0; //reset badge number
}
}
You may need to find a reader that offer a continuously reading, as I know almost of Wiegand Reader in the market can't perform a continuously reading because they have a "onboard" control that controls this...
Maybe you can try with Arduino Serial RFID Reader...
try a this timer libary Timer1 and mayby try this code it worked for me, my tags and cards now reads continuously.
Greetings from Denmark
Gregor
#include <Timer1.h>
//******************************************************************
// ATmega168, ATmega328:
// - Using Timer 1 disables PWM (analogWrite) on pins 9 and 10
// ATmega2560:
// - Using Timer 1 disables PWM (analogWrite) on pins 11 and 12
// - Using Timer 3 disables PWM (analogWrite) on pins 2, 3 and 5
// - Using Timer 4 disables PWM (analogWrite) on pins 6, 7 and 8
// - Using Timer 5 disables PWM (analogWrite) on pins 44, 45 and 46
//******************************************************************
unsigned int lastTime;
#include <SoftwareSerial.h>
SoftwareSerial RFID = SoftwareSerial(2,4);
char character;
String our_id;
void setup()
{
// Disable Arduino's default millisecond counter (from now on, millis(), micros(),
// delay() and delayMicroseconds() will not work)
disableMillis();
// Prepare Timer1 to count
// On 16 MHz Arduino boards, this function has a resolution of 4us
// On 8 MHz Arduino boards, this function has a resolution of 8us
startCountingTimer1();
lastTime = readTimer1();
Serial.begin(9600);
RFID.begin(9600);
}
void loop()
{
unsigned int now = readTimer1();
while (RFID.available()>0)
{
character = RFID.read();
our_id += character;
lastTime = now;
}
if (our_id.length() > 10) {
our_id = our_id.substring(1,13);
Serial.println(our_id);
our_id = "";
}
delay(1000);
}
I am trying to attach a servo on an Arduino (branded) Robot but not sure whhich pin to use for the bellow code.
Most people seem to recommend to use pin 9 and 10 to control the servo for arduino Unos.
However, I can't use Pin 9 because that is already used as the Slave Select pin for the LCD.
I have tried attaching it to pins TKD0-TKD3 by calling them pins 19-22 in myservo.attach(). The code runs but the servo doesn't rotate and only gets hot and/or twitches.
Could the problem be something other than incorrect pin connection?
Thanks,
-M
I have been referencing these for the Control board pin mapping:
http://arduino.cc/en/Main/Robot)
http://fabcirablog.weebly.com/blog/grappling-with-the-arduino-robot-control-board
#include <Servo.h>
Servo myservo; // create servo object to control a servo
int pos = 0;
void setup()
{
myservo.attach(19); // attaches the servo on pin 9 to the servo object
}
void loop()
{
for(pos = 0; pos < 60; pos += 1)
{
myservo.write(pos);
delay(15);
}
for(pos = 60; pos>=1; pos-=1)
{
myservo.write(pos);
delay(15);
}
}
You have this robot, right?
Arduino Robot
And you are using a classic servo (3 pins, yellow red and black cable)? If so.... Watch out. According to the schematic, the pinout of the connector on the board (e.g. TKD0) is
+5V
AD1
GND
While usually servos have
DATA
+5V
GND
So.. you have to make a short cable to invert the pins.
If that's not the problem.. Are you sure that 19 is the right number for the pin? I can't find references, but i suggest you to call it TKD0 (which is probably a macro defining the right pin), as arduino designers suggest you.
So my problem is as title says: Arduino UNO analogRead always returns 1023.
But when I burn the same sketch in Arduino Mega 2650 everything works like a charm.
I have tried to change Atmel chips on the UNO, have tried like 3 of them (ATMEGA328P-PU) and nothing changes.
I'm trying to count signals from a hall effect sensor and display the count on a 7 segment display.
Here is the code:
#include "SevSeg.h"
SevSeg sevseg;
volatile int rpmcount;
void setup() {
Serial.begin(9600);
pinMode(2,INPUT_PULLUP);
rpmcount = 0;
sevseg.Begin(1,3,4,5,6,7,8,9,10,11,12,13);
}
int border=15;
void loop() {
int tmp=0;
tmp = analogRead(0);
if(!digitalRead(2))rpmcount=0;
Serial.println(tmp,DEC);
if(tmp<=border && res >border){
rpmcount++;
if(rpmcount>9999)rpmcount=0;
}
res=tmp;
sevseg.NewNum(rpmcount,(byte) 0);
sevseg.PrintOutput();
}
Any help would be much appreciated
This sounds to me as if you had the internal pullup resistor on the ADC pin enabled.
generic checklist:
ACD bit in ACSR is 0 (comparator enable)
MUX bits in ADMUX set properly
correct AREF selected
ADC pin set as input
internal pull up resistors are deselected