AC dimmer using micropython - esp8266

I want to control AC Light Dimmer using Micro Python with ESP8266. I am not getting any libraries or examples related to this.Could anyone please help me with this
Thanks in advance!

Actually, it depends on which type of AC dimmer you have. I would expect something like RobotDyn AC dimmer:
Robodyn AC dimmer
In this case the regulation is not so easy like in the case of standard DC PWM (please don't let youself being confused by PWM pin, it is not real PWM). This module is standard triac dimmer which needs controlled dimming process (see this schematics).
The way how regulation works is based on the fact that you know when AC sine goes through zero (twice per period). Therefore there is Z-C input pin. When voltage goes through zero, you open triac for a while and cut off part of sine. Thats about regulation.
Wave regulation image
And this is what your dimmer driver shall do. This is not easy task in micropython as it requires to involve interrupts. You can see following code which I tried on HW and which was "working":
from machine import Timer, Pin
from micropython import alloc_emergency_exception_buf
from math import acos, pi
class Dimmer:
def __init__(self, pwm_pin, zc_pin, fpulse = 4000):
alloc_emergency_exception_buf(100)
self._cnt = 0
self._freq = 0
self._timer = Timer(2)
self._mode = Timer.ONE_SHOT
self._pwm = Pin(pwm_pin, Pin.OUT)
self._fpulse = fpulse
self._ppulse = 100.0 / fpulse + 0.11
self._zc = Pin(zc_pin, Pin.IN)
self._val = 1
self._zc.irq(trigger = Pin.IRQ_RISING | Pin.IRQ_FALLING, handler = self._zeroDetectIsr)
def _zeroDetectIsr(self, pin):
if 0 == self._freq:
self._pwm.on()
return
if 0 > self._freq:
self._pwm.off()
return
self._cnt += 1
if 1 == self._cnt:
self._timer.init(freq = self._freq, mode = self._mode, callback = self._dimmDelayIsr)
def _dimmDelayIsr(self, _timer):
if 1 == self._cnt:
self._pwm.on()
self._timer.init(freq = self._fpulse, mode = self._mode, callback = self._dimmDelayIsr)
else:
self._pwm.off()
self._cnt = 0
#property
def value(self):
return self._val
#value.setter
def value(self, p):
p = min(1, max(0, p))
if not self._val == p:
self._val = p
p = acos(1 - p * 2) / pi
if p < self._ppulse:
f = -1
elif p > 0.99:
f = 0
else:
f = 100 / (1 - p)
self._freq = int(f)
return self._val
Just note that unlike transistor, triac holds opened state till voltage on it drops to 0, so you can even use just short pulse to open it.
Use of driver is then simple:
from dimmer import Dimmer
dimmer = Dimmer(4, 2)
dimmer.value = 0.3
Unfortunately, micropython on ESP32 is locking interrupts quite often, so whole stuff works only when nothing is happening around. Most visible problems was around print function which was sometimes able to block for several AC sine periods, what caused visible bulb blinking. Unfortunately I would expect something similar in the case of WiFi communication.
The conclusion here is that the best solution is to use some cheep AVR based board and write code in C++ which will just care about dimming and nothing else. Such board can be connected to ESP board over I2C bus and ESP only sends command to set dimmer value.

Related

Can't calculate the right Volume RSI in MQL4 with a functioning Pine-Script Example

I want to "translate" a Pine-Script to MQL4 but I get the wrong output in MQL4 compared to the Pine-Script in Trading-view.
I wrote the Indicator in Pine-Script since it seems fairly easy to do so.
After I got the result that I was looking for I shortened the Pine-Script.
Here the working Pine-Script:
// Pinescript - whole Code to recreate the Indicator
study( "Volume RSI", shorttitle = "VoRSI" )
periode = input( 3, title = "Periode", minval = 1 )
VoRSI = rsi( volume, periode )
plot( VoRSI, color = #000000, linewidth = 2 )
Now I want to translate that code to MQL4 but I keep getting different outputs.
Here is the MQL4 code I wrote so far:
// MQL4 Code
input int InpRSIPeriod = 3; // RSI Period
double sumn = 0.0;
double sump = 0.0;
double VoRSI = 0.0;
int i = 0;
void OnTick() {
for ( i; i < InpRSIPeriod; i++ ) {
// Check if the Volume is buy or sell
double close = iClose( Symbol(), 0, i );
double old_close = iClose( Symbol(), 0, i + 1 );
if ( close - old_close < 0 )
{
// If the Volume is positive, add it up to the positive sum "sump"
sump = sump + iVolume( Symbol(), 0, i + 1 );
}
else
{
// If the Volume is negative, add it up to the negative sum "sumn"
sumn = sumn + iVolume( Symbol(), 0, i + 1 );
}
}
// Get the MA of the sump and sumn for the Input Period
double Volume_p = sump / InpRSIPeriod;
double Volume_n = sumn / InpRSIPeriod;
// Calculate the RSI for the Volume
VoRSI = 100 - 100 / ( 1 + Volume_p / Volume_n );
// Print Volume RSI for comparison with Tradingview
Print( VoRSI );
// Reset the Variables for the next "OnTick" Event
i = 0;
sumn = 0;
sump = 0;
}
I already checked if the Period, Symbol and timeframe are the same and also have a Screenshoot of the different outputs.
I already tried to follow the function-explanations in the pine-script for the rsi, max, rma and sma function but I cant get any results that seem to be halfway running.
I expect to translate the Pine-Script into MQL4.
I do not want to draw the whole Volume RSI as a Indicator in the Chart.
I just want to calculate the value of the Volume RSI of the last whole periode (when new candel opens) to check if it reaches higher than 80.
After that I want to check when it comes back below 80 again and use that as a threshold wether a trade should be opened or not.
I want a simple function that gets the Period as an input and takes the current pair and Timeframe to return the desired value between 0 and 100.
Up to now my translation persists to provide the wrong output value.
What am I missing in the Calculation? Can someone tell me what is the right way to calculate my Tradingview-Indicator with MQL4?
Q : Can someone tell me what is the right way to calculate my Tradingview-Indicator with MQL4?
Your main miss of the target is in putting the code into a wrong type of MQL4-code. MetaTrader Terminal can place an indicator via a Custom Indicator-type of MQL4-code.
There you have to declare so called IndicatorBuffer(s), that contain pre-computed values of the said indicator and these buffers are separately mapped onto indicator-lines ( depending on the type of the GUI-presentation style - lines, area-between-lines, etc ).
In case you insist on having a Custom-Indicator-less indicator, which is pretty legal and needed in some use-cases, than you need to implement you own "mechanisation" of drawing lines into a separate sub-window of the GUI in the Expert-Advisor-code, where you will manage all the settings and plotting "manually" as you wish, segment by segment ( we use this for many reasons during prototyping, so as to avoid all the Custom-Indicator dependencies and calling-interface gritty-nitties during the complex trading exosystem integration - so pretty well sure about doability and performance benefits & costs of going this way ).
The decision is yours, MQL4 can do it either way.
Q : What am I missing in the Calculation?
BONUS PART : A hidden gem for improving The Performance ...
In either way of going via Custom-Indicator-type-of-MQL4-code or an Expert-Advisor-type-of-MQL4-code a decision it is possible to avoid a per-QUOTE-arrival re-calculation of the whole "depth" of the RSI. There is a frozen-part and a one, hot-end of the indicator line and performance-wise it is more than wise to keep static records of "old" and frozen data and just update the "live"-hot-end of the indicator-line. That saves a lot of the response-latency your GUI consumes from any real-time response-loop...

lua basic how to loop?

hi I'm kinda new in this scripting im trying to make automation script from macro app ios/android that using lua language called autotouch https://autotouch.net/server/doc/en.html#autotouch-document
i'm clueless where to start from scratch is there lua function like this?
searching for color in whole screen then tap it
the script is similar to this
loop
color = PixelSearch(x coord, y coord, #somergbColor codes)
If (color) is found in screen then
tap it
else
tap teleport skill/walk to search for target button
endif
endloop
end
The loop isn't too specific. You could do the inner actions in two 2 ways using findColor(color, count, region) provided by AutoTouch, or getColor(x, y) (essentialy faster in octet-size than getColors(locations) in my opinion, because of the return's value; but the problem is from the developers if they don't put a byte array API for handling lower and unsigned integers, of course).
findColor() is being limited to only find 1 pixel at max..
local target = 0x447111;
local location = findColor(target, 1);
local first = location[1];
if location and first then
touchDown(1, first[1], first[2]);
else
-- I don't understand this action?
end
So, if you want to find your color manually you can use getColor().
local target = 0x447111;
local w, h = getScreenResolution();
local broken = false;
for y = 1, h do
for x = 1, w do
local cur = getColor(x, y);
if cur == target then
broken = true;
break;
end
end
if broken then
break;
end
end
if broken then
touchDown(1, 1, 1);
end

MT7620A--How to enable RGMII port

funcctional Block Diagram
Hi,
I do have a MT7620 Board, and want to use RGMII port, on the datasheet comes with board, it shows me a diagram like what I post. the red circle area. shows that somehow the RGMII comes in to the switch port which by my understanding is the LAN port on the board.
my question is how I can enable the RGMII, and connect it with my device(which port on the board I should connect). Is it a auto config or I need to do something for it(eg, DTS).
I am new to this, so please answer more detail. and If I make anything not clear, ask. Thanks
Has been days, but no one come to answer, just post what I found for my question.
I borrow some machine from lab so that I can check the signal on board. I connect the board to internet and my laptop on the other side. and open a video page on browser. so that there will be some data flow between board and my laptop.
I use the machine to check the pins on the board which the circuit map shows belong to RGMII. but there is nothing, no signal comes up. which means the RGMII pins doesn't work by default.
So I assume that I need to edit some DTS to enable the RGMII signal. But I have no idea how to do this now. If anyone knows it. Please write it down. Thanks.
I am not sure of the specific board you are using , but yes the RGMII pins have to configured. If connecting a PHY to a microcontroller, you need to specify the negotiation speed for the TX and RX clock, along with other data pins. Something similar to this -
const IfxGeth_Eth_RgmiiPins Rgmiipins = {
//Set the reference clock
.txClk = &IfxGeth_TXCLK_P11_4_OUT ,
.txd0 = &IfxGeth_TXD0_P11_3_OUT ,
.txd1 = &IfxGeth_TXD1_P11_2_OUT ,
.txd2 = &IfxGeth_TXD2_P11_1_OUT ,
.txd3 = &IfxGeth_TXD3_P11_0_OUT ,
.txCtl = &IfxGeth_TXCTL_P11_6_OUT ,
.rxClk = &IfxGeth_RXCLKA_P11_12_IN ,
.rxd0 = &IfxGeth_RXD0A_P11_10_IN ,
.rxd1 = &IfxGeth_RXD1A_P11_9_IN ,
.rxd2 = &IfxGeth_RXD2A_P11_8_IN ,
.rxd3 = &IfxGeth_RXD3A_P11_7_IN ,
.rxCtl = &IfxGeth_RXCTLA_P11_11_IN ,
.mdc = &IfxGeth_MDC_P12_0_OUT ,
.mdio = &IfxGeth_MDIO_P12_1_INOUT ,
.grefClk = &IfxGeth_GREFCLK_P11_5_IN ,
};
Now you say you are connecting it to a laptop. I did not understand your question completely, but if there is a linux kernel involved somewhere, then yes you need to modify the Device Tree. Here is a link you can start with. Here is an example, taken from the same source-
ethernet#e000b000 {
compatible = "cdns,zynq-gem", "cdns,gem";
reg = <0xe000b000 0x1000>;
status = "okay";
interrupts = <0x0 0x16 0x4>;
clocks = <0x1 0x1e 0x1 0x1e 0x1 0xd>;
clock-names = "pclk", "hclk", "tx_clk";
#address-cells = <0x1>;
#size-cells = <0x0>;
local-mac-address = [00 0a 35 00 00 00];
phy-mode = "rgmii-id";
xlnx,ptp-enet-clock = <0x6750918>;
phy-handle = <0x4>;
mdio {
#address-cells = <0x1>;
#size-cells = <0x0>;
phy#1 {
compatible = "realtek,RTL8211E";
device_type = "ethernet-phy";
reg = <0x1>;
linux,phandle = <0x4>;
phandle = <0x4>;
};
};
};
Hope this will get you started.

Change position on Y axis based on distance

I've been trying to make a game where you're in a square and when you go to the sides, parts come up and block you.
I've gotten far to the point where it's working fine, except for a few problems:
the parts go below the square when not raised, I want them to be visible when they're not raised
the parts go down when you jump, making it easy to escape.
the parts go up too early
This is the code that deals with the wall positioning.
for _, v in pairs(model:GetChildren()) do
if string.sub(v.Name,1,4) == "Wall" then
local walls = {}
walls[v] = {v.CFrame,Vector3.new(1, 1, 1)}
game:GetService("RunService").RenderStepped:connect(function()
if(workspace[game.Players.LocalPlayer.Name]:FindFirstChild("HumanoidRootPart")) then
local mag = (v.Position - workspace[game.Players.LocalPlayer.Name]:FindFirstChild("HumanoidRootPart").Position).magnitude
sizeFactor = math.floor(mag)
v.CFrame = walls[v][1]*CFrame.new(0,-sizeFactor+(walls[v][1].Y*1.8),0)
end
end)
end
end
You can see my game here: https://www.roblox.com/games/400391033/Marble-walls
See commented code.
for _, v in pairs(model:GetChildren()) do
if string.sub(v.Name,1,4) == "Wall" then
local walls = {}
walls[v] = {v.CFrame,Vector3.new(1, 1, 1)}
game:GetService("RunService").RenderStepped:connect(function()
if(workspace[game.Players.LocalPlayer.Name]:FindFirstChild("HumanoidRootPart")) then
local mag = (v.Position - workspace[game.Players.LocalPlayer.Name]:FindFirstChild("HumanoidRootPart").Position).magnitude
if (mag <= 2) then --[[
Currently your issue is that you never actually do ANYTHING regarding magnitude
you essentially change the y-Axis as soon as the player spawns.. hence why it does it too early
kappa
]]
sizeFactor = math.floor(mag)
v.CFrame = walls[v][1]*CFrame.new(0,-sizeFactor+(walls[v][1].Y*1.8),0)
end;
end
end)
end
end

Nokia 5110 LCD initialization issue

I am trying to connect Nokia 5110 LCD to BeagleBone Black Rev-C over SPI protocol.
The connections are exactly as shown on the page 6 of:
Nokia5110-BeagleBone Black Connections
I wrote a C equivalent of Arduino's code for Philips PCD8544 (Nokia 3310) driver.
Where I export the required GPIO ports and send commands and data over SPI interface.
I successfully installed and ran Adafruit's python-library:
Adafruit Nokia LCD
My problem is
I have a strange issue, when I run this python code first and then my C code, the code works perfect!
But if I run my C code before the python code, I get no output. Logic says that the python
code must be initializing something that I am missing in my code.
Here's how I initialize the LCD:
fd_spi_dev = open(device, O_RDWR);
//set mode
mode = SPI_MODE_0;
ioctl(fd_spi_dev, SPI_IOC_WR_MODE, &mode);
ioctl(fd_spi_dev, SPI_IOC_RD_MODE, &mode);
//set max bitrate
speed = 4000000;
ioctl(fd_spi_dev, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
ioctl(fd_spi_dev, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
// set an msb first
lsbsetting = 0;
ioctl(fd_spi_dev, SPI_IOC_WR_LSB_FIRST, &lsbsetting);
// set bits per word
bits = 8;
ioctl(fd_spi_dev, SPI_IOC_WR_BITS_PER_WORD, &bits);
ioctl(fd_spi_dev, SPI_IOC_RD_BITS_PER_WORD, &bits);
lcd_write_cmd(0x21); // LCD extended commands
lcd_write_cmd(0xB8); // set LCD Vop (contrast)
lcd_write_cmd(0x04); // set temp coefficient
lcd_write_cmd(0x14); // set biad mode 1:40
lcd_write_cmd(0x20); // LCD basic commands
lcd_write_cmd(0x09); // LCD all segments on
/* I am expecting to see all segments lit here */
sleep(5);
lcd_write_cmd(0x0C); // LCD normal video
void lcd_write_cmd(uint8_t cmd) {
uint8_t *tx = &cmd;
uint8_t rx;
uint32_t len = 1;
struct spi_ioc_transfer tr = {
.tx_buf = (uint32_t)tx,
.rx_buf = (uint32_t)&rx,
.len = len,
.delay_usecs = delay,
.speed_hz = speed,
.bits_per_word = bits,
.cs_change = 1,
};
size = write(fd_dc_val, "0", 1);
size = write(fd_cs_val, "0", 1);
ioctl(fd_spi_dev, SPI_IOC_MESSAGE(1), &tr);
write(fd_cs_val, "1", 1);
}
I am a novice in embedded programming. I would greatly appreciate any help. Thank you.
If you're not missing an initialization step (and I haven't checked you against the 5110 datasheet), it must either be something wrong with your ioctls or a timing issue.
You could try using a library that abstracts away the ioctl calls to rule that out (I'm partial to my own: https://github.com/graycatlabs/serbus ;).
If it still doesn't work with that then I'd say it's probably a timing issue - Python is a lot slower than C when it comes to file I/O, so it might not be giving the LCD driver enough time to update after some of the commands - check the datasheet to see if it needs you to give it some time after any of the commands.

Resources