ESP8266 5v Relay USB Disconnection issue - esp8266

Issue
-When using the ESP8266 wired up in this way it will randomly disconnect the USB interface when it powers the relay. It may then re-connect but is sporadic.
-The code can be viewed below, but essentially the relay is powered for 300ms then waits 10 seconds to loop.
Wiring Diagram https://i.stack.imgur.com/4mycx.png
Tests:
I have swapped out the relay, pump, ESP8266, aswell as re-wiring the circuit multiple times to check for a short. I also have a integer incrementing every loop cycle, when the ESP8266 is able to re-connect it will print this variable, which shows the board is not crashing:
Serial output
https://i.stack.imgur.com/ziM8g.png
I then modified the diagram so the 5v power was not in parallel, but where two different power sources, one for the ESP8266 and one for the pump circuit, however the same issue was observed:
Test Wiring Diagram https://i.stack.imgur.com/7S0aP.png
Question:
Why does the USB disconnect when sending the control signal to the relay?
Is there a way to mitigate this?
Code:
int relayInput = 5; // the input to the relay pin
int debug_test = 0;
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
pinMode(relayInput, OUTPUT); // initialize pin as OUTPUT
}
void loop() {
// put your main code here, to run repeatedly:
debug_test ++ ;
Serial.println(debug_test);
digitalWrite(relayInput, HIGH); // turn relay on
Serial.println("Water on!");
delay(300);
digitalWrite(relayInput, LOW); // turn relay off
Serial.println("Water off!");
Serial.println("Waiting 10 seconds");
delay(10000);
}
Parts:
Pump - https://www.ebay.co.uk/itm/Mini-Water-Pump-DC-3V-4-5V-Fish-Tank-Fountain-Aquarium-Submersible-White-Parts/174211676084?hash=item288fd337b4:g:128AAOSwfQteYWF3
ESP8255 - https://www.amazon.co.uk/gp/product/B07F5FJSYZ/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1
Relay - https://www.amazon.co.uk/gp/product/B07BVXT1ZK/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1

Ok, so researching in to this, it seems when the pump is on it pulls more current (amps) than the PC can provide.
This will be used connected to a external power source which should supply enough current to it, however I also wanted the flexibility to connect it to a PC with a serial connection to troubleshoot.
So in the end something like this:
https://i.stack.imgur.com/MKD1h.png

You are driving a 5v relay module with 3.3v output, which works perfectly for some people but it depends on the relay module and the board, this might be the problem. or the relay draws more than 12mA which is the maximum current can the ESP8266's GPIO deliver.
so I suggest you use an external power source for the relay and control it through the pin (D1 in your case).
Or just use a generic 5v relay with an external 5v power source and control it using a transistor, here is a circuit.
Additional information: https://electronics.stackexchange.com/questions/213051/how-do-i-use-a-5v-relay-with-a-3-3v-arduino-pro-mini?

Related

How to determine if ESP32 MicroPython wifi access point is ready to show IP address?

I have an ESP32 microcontroller with MicroPython 1.19.1 that I'm setting up as a wifi access point. But, when I attempt to print the IP address with print(f'{wlan.ifconfig()}') it gets stuck in a reboot loop.
Here's the code in my boot.py:
from network import WLAN, AP_IF
from config import AP_NAME, AP_PASS
print('Starting in wifi access point mode...')
wlan = WLAN(AP_IF)
wlan.config(authmode=3, essid=AP_NAME, password=AP_PASS)
wlan.active(True)
while (wlan.active() == False):
print('.')
print(f'SSID: {AP_NAME}')
print(f'Password: {AP_PASS}')
print(f'{wlan.ifconfig()}')
Commenting out the print(f'{wlan.ifconfig()}') fixes the reboot loop, as does inserting a delay just before the statement.
This leads me to believe the access point is not fully ready by the time I'm calling ifconfig(). But, I'm working under the assumption the while (wlan.active() == False) is supposed to take care of that. Though in the serial output, there's not a single dot printed to indicate it looped even once.
Serial output looks like this (after inserting a delay to mitigate the reboot loop):
Starting in wifi access point mode...
SSID: Lab
Password: ********
('192.168.4.1', '255.255.255.0', '192.168.4.1', '0.0.0.0')
If the while loop were actually waiting for the access point to come up, I would expect a few lines with dots between the 'Starting' message and the printing of SSID. So I'm thinking wlan.active() is just telling me what I set in the line above: wlan.active(True) and is not a true reflection of the access point's readiness.
I tried help(wlan) to see what methods might be available to determine the state of the access point. Some of the more promising ones and their results are shown below.
>>> wlan.active()
True
>>> wlan.isconnected()
False
>>> wlan.status()
>>>
I'm not surprised by isconnected() returning false since it's probably just for wifi station mode. I had high hopes for status(), but it only returns None
Every tutorial I've found so far uses the while loop to check active(), but obviously that's not working. Sticking a random delay in seems like a bad solution.
Is there a reliable way to ensure the access point is fully ready before asking for its IP address?

Serial Communication of Sony Spresense with ESP8266 E12

I'm trying to create a simple serial communication between my ESP8266 E12 and a Sony Spresense. I have connected the Spre.RX with ESP.TX, the Spre.TX with ESP.RX and Spre.GND with ESP.GND.
Receiver:
byte rcvByte;
void setup() {
Serial.begin(9600);
while (!Serial) {;}
Serial.println("Receiving");
}
void loop() {
if (Serial.available()) {
rcvByte = Serial.read();
if (rcvByte == 'H') {
Serial.println("High");
}
if (rcvByte == 'L') {
Serial.println("Low");
}
}
}
Sender:
void setup() {
Serial.begin(9600);
while (!Serial) {;}
Serial.println("Sending");
}
void loop() {
Serial.print('H');
delay(1000);
Serial.print('L');
delay(1000);
Serial.println();
}
Unfortunately, nothing happens. I tried both, ESP as Sender and Spresense as Receiver and vice versa.
It works like a charm when I connect my ESP and a Arudino Uno, in both ways.
Do I have to enable the RX/TX pins with the Spresense somehow? I have tried the pins on the developer board as well as the small board directly. Any suggestions?
I took a quick look into this and my best guess, or tip after checking the code is to try the following on the Spresense side:
Simply change Serial to Serial2.
void setup() {
Serial2.begin(9600);
while (!Serial2) {;}
Serial2.println("Sending");
}
void loop() {
Serial2.print('H');
delay(1000);
Serial2.print('L');
delay(1000);
Serial2.println();
}
I have not tested so please do if you can.
I noticed a small detail in the hardware datasheet provided at:
Spresense Hardware Documents
In the section labeled - 2. Differences between Spresense and Arduino Uno:
It has a small table showing the comparison with explanations.
Located at the bottom of the table one can see the boxes for UART Serial communication.
Note the existence of two serial outputs on the spresense board. The Spresense Main board (smaller nano like) has a serial UART rx/tx pair with syntax variable -> "serial" but in addition the Spresense expansion shield also has a second UART RX/TX pair with syntax -> "serial2"
"The Spresense main board and extension board have UART terminals.
It is not possible to use the UART on both the main board and the extension board at the same time.
The extension board is configured to have the UART enabled when it is shipped. To use the UART pins on the main board when attached to the extension board, a 2.54mm pitch jumper have to be connected to pin 1 and 2 on JP10 of the extension board to disable the extension board UART. No jumper is supplied with the Spresense boards so this has to be purchased separately.
When the extension board UART is activated, the UART pins (D00, D01, D27 and D28) of the main board cannot be used as GPIO."
I ended up spending about three days pulling my hair out before i realized looking at documentation provides all the answers one could need..
The killer is in the details on this one.
This should provide some clarity to others experimenting with UART communication between spresense products while attempting utilize the expansion board.

ESP8266-01 loads from Arduino IDE but doesn't run

I had this working fine a few months ago but can't seem figure out what's changed. I have several ESP-01 and I can upload using Arduino IDE with Generic 8266 board profile but I can't get anything to run. Nothing shows on the Serial Monitor. I've tried simple code like:
void setup() {
// put your setup code here, to run once:
delay(1000);
Serial.begin(115200);
delay(1000);
Serial.println("Hello, you've entered setup()...");
}
void loop() {
// put your main code here, to run repeatedly:
Serial.println("Good day, you're in loop()...");
delay(2000);
}
I've tried using a jumper to 3.3v on the ENable pin and a 10k resister. I've removed the GPIO0 after programming. Nothing seems to work. I have 4 chips so I know I'm not doing something.
I have 3.3v on VCC (measured), nothing on RST, EN to VCC (tried 10k to VCC), TX - RX, RX - TX, 0 - Gnd for programming, nothing on 2, Gnd - Gnd
I found the answer for this problem. It seems that the ESP-01 chip must have 10k resisters on GPIO 0, GPIO 2, and reset to VCC in order function properly. Although the chip seemed to accept the flash, the floating pins were causing problems. Once I added the pullup resisters, it was like magic, everything started working.
Just switch to boards version 2.4. It will work then

Delphi - Is it possible to detect if the Screen monitor is ON or OFF by software? [duplicate]

Does anyone know if there is an API to get the current monitor state (on or off) in Windows (XP/Vista/2000/2003)?
All of my searches seem to indicate there is no real way of doing this.
This thread tries to use GetDevicePowerState which according to Microsoft's docs does not work for display devices.
In Vista I can listen to GUID_MONITOR_POWER_ON but I do not seem to get events when the monitor is turned off manually.
In XP I can hook into WM_SYSCOMMAND SC_MONITORPOWER, looking for status 2. This only works for situations where the system triggers the power off.
The WMI Win32_DesktopMonitor class does not seem to help out as well.
Edit: Here is a discussion on comp.os.ms-windows.programmer.win32 indicating there is no reliable way of doing this.
Anyone else have any other ideas?
GetDevicePowerState sometimes works for monitors. If it's present, you can open the \\.\LCD device. Close it immediately after you've finished with it.
Essentially, you're out of luck—there is no reliable way to detect the monitor power state, short of writing a device driver and filtering all of the power IRPs up and down the display driver chain. And that's not very reliable either.
You could hook up a webcam, point it at your screen and do some analysis on the images you receive ;)
Before doing anything based on the monitor state, just remember that users can use a machine with remote desktop of other systems that don't require a monitor connected to the machine - so don't turn off any visualization based on the monitor state.
You can't.
Look like all monitor power capabilities connected to the "power safe mode"
After searching i found here code that connecting between SC_MONITORPOWER message and system values (post number 2)
I use the code to testing if the system values is changing when i am manually switch off the monitor.
int main()
{
for(;monitorOff()!=1;)
Sleep(500);
return 0;
}//main
And the code is never stopped, no matter how long i am switch off my monitor.
There the code of monitorOff function:
int monitorOff()
{
const GUID MonitorClassGuid =
{0x4d36e96e, 0xe325, 0x11ce,
{0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18}};
list<DevData> monitors;
ListDeviceClassData(&MonitorClassGuid, monitors);
list<DevData>::iterator it = monitors.begin(),
it_end = monitors.end();
for (; it != it_end; ++it)
{
const char *off_msg = "";
//it->PowerData.PD_PowerStateMapping
if (it->PowerData.PD_MostRecentPowerState != PowerDeviceD0)
{
return 1;
}
}//for
return 0;
}//monitorOff
Conclusion : when you manually switch of the the monitor, you cant catch it by windows (if there is no unusual driver interface for this), because all windows capabilities is connected to "power safe mode".
In Windows XP or later you can use the IMSVidDevice Interface.
See
http://msdn.microsoft.com/en-us/library/dd376775(VS.85).aspx
(not sure if this works in Sever 2003)
With Delphi code, you can detect invalid monitor geomerty while standby in progress:
i := 0
('Monitor'+IntToStr(i)+': '+IntToStr(Screen.Monitors[i].BoundsRect.Left)+', '+
IntToStr(Screen.Monitors[i].BoundsRect.Top)+', '+
IntToStr(Screen.Monitors[i].BoundsRect.Right)+', '+
IntToStr(Screen.Monitors[i].BoundsRect.Bottom))
Results:
Monitor geometry before standby:
Monitor0: 0, 0, 1600, 900
Monitor geometry while standby in Deplhi7:
Monitor0: 1637792, 4210405, 31266576, 1637696
Monitor geometry while standby in DeplhiXE:
Monitor0: 4211194, 40, 1637668, 1637693
This is a really old post but if it can help someone, I have found a solution to detect a screen being available or not : the Connecting and Configuring Displays (CCD) API of Windows.
It's part of User32.ddl and the interesting functions are GetDisplayConfigBufferSizes and QueryDisplayConfig. It give us all informations that can be viewed in the Configuration Panel of windows.
In particular the PathInfo contains a TargetInfo property that have a targetAvailable flag. This flag seems to be correctly updated on all the configurations I have tried so far.
This allow you to know the state of every screens connected to the PC and set their configurations.
Here a CCD wrapper for .Net
If your monitor has some sort of built-in USB hub, you could try and use that to detect if the monitor is off/on.
This will of course only work if the USB hub doesn't stay connected when the monitor is consider "off".

get keyboard input contiki

I want to know how can I get a keyboard input in contiki os.
I already tried getchar(),getch(),scanf(),gets() and none worked, so I want to know if somebody can help me.
getchar,getch,scanf,gets are sort of POSIX things that read from files (e.g. stdin) --- these don't exist in Contiki (all though you could probably use them with the native platform).
So the first question to ask is what platform are you using and what do you mean by "keyboard". If keyboard means typing characters that are sent via a serial port from a computer then you have to know where they are received on the thing running Contiki. A typical arrangement is to receive characters on a uart, say, uart1.
In this case, contiki uses a callback such as uart1_input_handler that will be defined by the application. Platform main loops will check if there are characters to send to the input_handler and then check that an input_handler is defined. If so, will call something like uart1_input_handler(c).
You can see this code for the various platforms by grepping for uart1_input_handler:
platform/redbee-econotag/contiki-mc1322x-main.c: uart1_input_handler(uart1_getc());
cpu/msp430/dev/uart1x.c: if(uart1_input_handler(c)) {
cpu/stm32w108/dev/uart1.c: uart1_input_handler(c);
etc...
Some examples that register an input handler and process the characters:
example/shell:
/* set up the shell */
uart1_set_input(serial_line_input_byte);
serial_line_init();
serial_shell_init();
slip, in examples/ipv6/rpl-border-router/slip-bridge.c
slip_set_input_callback(slip_input_callback);
My guess for what you want to do would be to start with the shell examples and try to get those working.
The example cited below is from the Wiki pages of contiki on github. It demonstrates how the contiki specific mechanism for serial input works. Like mariano mentioned above that a callback has to be defined for the serial drivers specific to the platform you are using. I have used for ex. "rs232_set_input(RS232_PORT_0, serial_line_input_byte) ; " for my atmega128 MCU. The serial i/o drivers use this callback mechanism to post input characters to the "serial_line_process" defined in serial-line.c file. This process then broadcasts the serial_line_event_message to all processes along with the data read on the serial line. A process like the eg. stated below, can catch this event and process the input as per the requirements.
The callback mentioned above is defined in $(CONTIKI)/core/dev/serial-line.c. Check that out.
Once you initialise it using serial_line_init(), you are good to go.
#include "contiki.h"
#include "dev/serial-line.h"
#include <stdio.h>
PROCESS(test_serial, "Serial line test process");
AUTOSTART_PROCESSES(&test_serial);
PROCESS_THREAD(test_serial, ev, data)
{
PROCESS_BEGIN();
for(;;) {
PROCESS_YIELD();
if(ev == serial_line_event_message) {
printf("received line: %s\n", (char *)data);
}
}
PROCESS_END();
}
I assume you use COOJA (or maybe you connected a keyboard to your device so my answer will not be correct).
COOJA is an emulator, not a simulator.
If you want a responsive design, use the sensor button (on sky platform for example)
SENSORS_ACTIVATE(button_sensor);
/* Wait until we get a sensor event with the button sensor as data. */
PROCESS_WAIT_EVENT_UNTIL(ev == sensors_event &&
data == &button_sensor);
Hope it helped.

Resources