Monday, November 5, 2018

October - more changes

Hello,

   The array is now more exposed to early sunlight. I've cut down trees in the line of sight of morning sun and now get a couple more hours of sunlight. Good timing since the neighbor's tall evergreens and the old oak, on the other side, have begun casting a shadow on the array in the two o'clock  zone.
   I repositioned the actuator arm's connection to the array, further from the center to get a wider range of azimuths. The array begins at 150 degrees and ends at 210 degrees. This can be increased by raising the array high enough to swing East to 180 degrees and West to 270 degrees, and using an actuator with a thirty inch reach. As is, the array will be stopped by ground contact at current exteemes. Since I've oriented the array South, 180 degrees, and 45 degrees elevation, the optimum for mmy latitude, noon is thirty degrees or 5-6 seconds, and evening is 11-12 seconds of on time.
  The array now moves five degrees for each second of on time. A total of twelve seconds moves the array between extremes and across sixty degrees of azimuth.
   I've scrapped the old actuator script and now am using a new manual adjustment script until I write a new acuator automation script.
   I'm considering using the sensor to align the array instead of calculations or interpolation.
There would need to be coding to eliminate stutters and shakes from minute changes in the environment. A sleep cycle lasting five minutes between moves, would work.
   If the ADS1115 should fail, a safety should be triggered to prevent array movement or switch to calculated or interpolated motion and print an error message.
   One of the ADS channels has had a problem for sometime. I replaced the ADS1115 with a new unit and the bad channel is still not functioning correctly. The new unit problem channel has an intermittent signal, meaning the wiring is probably faulty. I think I merely twisted the wires together and applied heatshrink. The signals are susceptible to line noise and this shows in the graphs of the channels. Shielded cable is needed, though the differential between channels and ground is correct. Since the readings are correct with respect to each other and five wire shielded cable is expensive, I'll forego the shielded cable unless actuator movement is effected if I use the sensor for array positioning.
   I need to solder all joints and connections.
   The controller was shutting down USB ports and reopening others, a sort of "wack-a-mole" with USB ports. Eventually, all ports ceased to function. I had read that fusible links were used to protect USB ports from over current states. I have made some unconventional power terminations over the last few months. I decided to keep the controller off line for a few weeks. When I reconnected, I had no problems and have had none since. I now make conventional power terminations. A power switch would be a helpful addition. An update: The problem reoccurred. On the advice of another RPi user, I'll add an FTDI-USB cable/connector. This is supposed to solve the problem. Updating the operating system may also work since the problem seems operating system related.
   A month or so past, I did another water check for the battery bank. The usual units needed water added. I had attached the desulphator device, but a month has passed and I have removed the device.
   As usual, more batteries are needed and more panels are needed. Two more batteries and six more panels are the near term goal. New or altered mounting of the array is also planned.
   Currently, my backup sytem consists of the C-60 Xantrex PW controller (not an MPPT device) and the old three hundred watt sine inverter. The inverter will drive LED lights and the laptop but not much else. Certainly neither of the refrigerators. I'm not sure about the water pump.
   I need to get system extra parts: a new MPPT contoller and a new inverter of at least a thousand watts, preferably two or three thousand watts and that is a pure sine wave inverter.

Friday, September 7, 2018

Setpember 7 update

My array is on the side of a hill.

To the East is an overgrown lot with wild trees and weeds.

To the West are several evergreen trees over 30 feet tall. Behind the trees and up the hill is a residence. These reduce the sunlight, especially in Winter when the light is most useful.

Down the hill is an eight foot tall wood plank fence in disrepair.

Up the hill is my residence.

I decided to clear off the overgrown brush on my lower lot, about 50ft  by 100ft. I thought I could gain some daylight time in the morning. I did. I bought an electric hedge trimmer and an electric  chainsaw. Clearing off the vegetation would be within the capabilities of the tools.

Before I cleared off the most relevant area, I started getting first strong light at ten o'clock. After clearing off that area, my daylight begins at nine o'clock.

If I can get the Eastern brush cleared, I could get first daylight unobstructed for a mile or two.
In summer, daylight is around six or seven in the morning. In Winter, first daylight is closer to seven or eight o'clock.

If I can get the evergreen trees removed on the Western side, I could extend my daylight length by another hour.

These obstruction issues are important. Especially in Winter when the sun rises low in the sky and is less intense. Oddly, the Sun is closest to the Earth early in January, contrary to what most would think. The Earth's nutation is greatest in Winter. This is the backward tilt of the Earth's axis. Locations below the Equator become closer to the Sun and locations North of the Equator become further from the Sun. This is where the seasons come from.

This brings me to an issue I need to think about and make a decision about. If the array is raised above the ground twenty or thirty feet, many of the local obstructions become null factors.

Of course, raising the array above the ground thirty feet, and maintaining the tracking system, is not an easy task.

The roof faces twenty degrees East of South. That is a workable bearing for roof mounting. The problem is the tracking system. A great deal of energy is lost if tracking is not used. The first approach that comes to mind is building a lumber frame attached to the roof to hold the array and tracking apparatus. This will give me both, tracking, and a South pointing direction for the array.
In Summer, there is no shortage of energy with a fixed tilt system. The array is fixed at forty-five degrees, the average tilt for the year. However, in the Winter, energy is more scarce and reorienting the array for Winter would be a good idea. This would require tilting the array forward, at least, twenty degrees. This brings up the question of the pivot point. Midpoint or top? A midpoint pivot is seesaw-like. A top pivot point fixes the bottom of the array pipe and moves the top or mid region. This is more difficult since the array has to stabilized in the lateral direction. This makes the seesaw pivot more attractive.
A tilt parallel to the roof of the house would be 30 degrees. The seesaw midpoint would have to raised off the roof enough to allow movement of the array to a greater degree.
Of some concern is the manner of attaching the lumber framework to the roof. Holes will leak and cause damage to the structure over time.
One possibility is a triangular frame with the top point at, and attached to, the chimney or the house framing there. The system would weigh enough that movement of the lower portion would not be a concern. In this situation, the house, itself, may become an obstacle to daylight, a factor that needs to be considered.

The array, in a simple form would not face directly South, but follow the roof structure. This is where the house, itself, mayblock sunlight.

Other approaches consist of ground mounting the array using long post or poles either embedded
in the ground, or in concrete blocks. The bigest issues with that approach are the difficulty in system maintenance and the permanence of the concrete blocks. Such blocks would be difficult or impossible to move. They take up yard space and are unsightly. If the blocks needed to be removed, a jack hammer would be needed, or a truck with a strong lift.

After a lot of thought about the matter, the last approach, concrete blocks and all, seems the better choice. No risk of damage to the house roof. No complex system to design and install. Direct Southern exposure is available.
If necessary, a deck could be built around the array, for maintenance purposes.

This idea came from another idea. Building a deck on the back of the house and letting the deck double as the array mounting platform. This is the best choice since an attractive deck is added and the array becomes an add on. Long treated lumber posts could be set into the ground or concrete filled containers, and project up and through the deck floor.

This, then, is the best idea, barring some technology I've not read about yet.
The back wall has two doors that can open onto the deck. The deck can be raised a couple of feet from the doorways to make basement access easy and lawn maintenance possible. Slits between deck floorboards are needed to provide drainage and some sunlight to the grass underneath.

If feasible, two arrays, one at each far corner of the deck, should be included in the design.
This will allow me to double my energy production. Combine a doubling of the number of panels with raising the wattage of the panels results in a potential twelve to twenty-four panels. If the panels are two hundred and fifty watts each, a total maximum production of three thousand to six thousand watts will be available. If the panels' wattage is raised to three hundred and fifty watts, the maximum output would be forty-two hundred to eighty-four hundred watts, or 3kW  and 6kW or 4.2kW and 8.4kW.
Something to think about.


Friday, July 27, 2018

July 27 update - actuator service installed and running as is sensor service


   Much has been done.
   The power supply booster arrived and has been adjusted and connected.
The script to operate the actuator is finished and runs as a service. The length of day to run, eight hours in summer, was programmed into the operation. The array is now repositioned every 28.4 minutes, throughout the day.
   The script takes into account the start up of the RPi at other than the 'official' start time, 10AM. If early, a wait time is calculated and run as a wait state. If late, the number of missed cycles is calulated and the array repositioned before entering the main routine.
   I replaced the four inch bolt, on the actuator mount, with an eight inch bolt that acts as a rail on which the actuator base can slide. This will eliminate the possibility of the actuator base binding.
   The sensor script is recording data daily, as a service. Some night samples were taken to test the small panels. Two of the panels began low frequency, amplitude modulated oscillation. The panels drop to zero volts in the dark. That test is done. The oscillations may be due to the 'dupont' connectors used.
   A semi-permanent form of wiring connection needs to be implemented. The existing connectors are for prototyping and aren't much good, even for that.
   Currently, I'm examining the installation of suspend and resume/reboot services for use in twenty-four hour system operation. Some operations are initialized every time the system boots and, therefore, need to be accommodated.
   The I2C expander arrived but the design has not been determined yet.
   The actuator power supply has been mounted on a section of vinyl gutter downspout. The fix is temporary but is neccessary to maintain front access at the same time as free air circulation, around the large heatsink on the back of the board.
   The following photos help depict the situation:



Saturday, July 14, 2018

relay safety, sensor, and I2C

I recently wrote and installed a service to initialize actuator power relays to a zero state. This will avoid any potential startup randomization of GPIO signals that may inadvertantly turn the relays on.

A power supply for actuator control, used in conjunction with the relay card, is on the way.
The p/s is a boost converter that will convert the battery bank's 24VDC to the 36VDC needed to run the actuator that positions the solar array.

The sensor output is recorded by a service, I've written, that records the values of A0,A1,A2,A3 and the date-time. The sensor output is sampled every 30 seconds. The functions for the sensor panels' voltages converge and diverge depending on the position of the sun and the degree of cloudiness.

A I2C multiplexor is en route from China. The device is, like most of the units I use, a breakout module. This one allows several I2C devices to communicate with the Raspberry Pi. This device elimnates the dependence on the number of access points to the I2C signal pins.
Previously, there was one set of I2C pins available on the GPIO connecot. This set was used by the RTC clock. I added a GPIO expansion module that sits on top of the Raspberry Pi. This gave me three GPIO headers to use. All I2C pins have been used. If I want to access more devices, such as sensors, I'll need to find away to expand the I2C access. This is what the I2C expander accomplishes.
The unit has connection points for several devices, each of which is selectable using address pins that can be addressed by GPIO signals.The unit can accomodate 8 devices. The units may be capable of daisychaining.

Sunday, June 17, 2018

Updates and future plans.


Prototyping board update:

   The 2.54mm pitch screw terminal block connectors arrived, as have the 12" 2x20 ribbon cable and new 5vdc relay card. re-wiring the relay card is done. F-F and F-M jumpers are on order as is a GPIO HAT for the Raspberry Pi. The screw terminals fit the header profile of the breakout modules and two standard headers for the ADS1115s remain.

A power connection has to be run from the array power lines (36vdc) to the relay card, to power the linear actuator (36vdc). I have been using the battery bank's 24vdc supply, however, that slows down the actuator's speed.

Connections between the Raspberry Pi's GPIO header and the breakout modules will be from the GPIO HAT using jumpers, screw terminals, wire and ribbon cable.

Current list of modules:
real time clock
8-channel multiplexor
analog to digital converters (ADS1115, PCF8591 multi-function)

Photo of the current state of the prototyping board:


The 5vdc relay card is on the left.
The buck converter is next to the relay card and will replace the Apple iPad power block as power supply.
The Raspberry Pi SoC (System on a Card) is in the middle. The RPi is a full fledged computer.
The PCF8591 is on the right.
Multiple ADS1115s will be placed on the far right.
The 8-channel multiplexor will be placed aboce the relay card, on top.
There is a temperature controlled relay, 20A, module that may be on the right.

The Temperature controlled relay module could be placed above the relay card and in the same  orientation. The multiplexor could be placed on the right and replace some of the ADS1115s.
There is no designated use for the temperature controlled relay card or the multiplexor.
They may be added later on, or left out.
The LCD panel voltmeter needs to be moved up to the prototyping board.

A 12vdc relay card arrived and will be kept for possible future use or resale.
Some consideration has to be made to implementing the plans for a dual-axis tracker and re-mounting of the array on an improved frame.

I need to double the number of batteries in the battery bank to optimize the MPPT controller's function. The controller limits current to 2A for each battery in the bank. This results in a mximum of 250w being drawn from the array. The array is capable of generating 580w.


Saturday, May 26, 2018

more system script work

System scripts have been installed, some with timers. A new script, actuator.py, has been written along with a service and timer. These combined with data collector script edits, plpace operation between 6:00AM and 6:00PM, daily, The edits in conjunction with the actuator script run the linear actuator three times each day. Two extensions, one at noon and one at 3:00PM, follow the position of the sun. The third is a retraction that restores the array to the sunrise position for the next day.

The script for the sensor needs to be written. The sensor needs to be accompanied by another, stationary sensor. The stationary sensor can be used as a reference for the sun path.

System Prototype PCB

Included here is an image of  the system's one pcb, a prototyping board used to mount several; components in one convenient place. The image is self-explanatory.




Sunday, May 13, 2018

more modifications to the system scripts


The data collection script needs to be modified to run between 6:00 AM and 6:00 PM.

The script that writes the header has been modified to skip if the header has been written already for a given day.

Sensor scripts need to be written.
Sensor data collection/storage, and condtion determination contingencies scripts are needed.
Cloudy days, overcast days, and changes in season.
Cross-validation with calculations will be simple.

s-retract.py actuator script


import RPi.GPIO as GPIO
import time
# CHECK wires at RPi header for loose connections when problems occur
# HIGH is low and LOW is high in GPIO using the RPi.GPIO library

# ADD PWM
# 35 seconds is the actuator run time from beginning to end.

# Initialize software and hardware
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(26,GPIO.OUT)
GPIO.setup(19,GPIO.OUT)
GPIO.setup(13,GPIO.OUT)
GPIO.setup(6,GPIO.OUT)
# Shut all relays off. Relays are usually off on power up.
GPIO.output(26,GPIO.HIGH)
GPIO.output(19,GPIO.HIGH)
GPIO.output(13,GPIO.HIGH)
GPIO.output(6,GPIO.HIGH)
print('Initialized.')


#####################
# Do this at the end of the day, at 6:00 PM

#Retract on
GPIO.output(26,GPIO.LOW)
GPIO.output(19,GPIO.LOW)
print('Retracting...')
time.sleep(32)
#Retract off
GPIO.output(26,GPIO.HIGH)
GPIO.output(19,GPIO.HIGH)
print('Retraction done.')


s-extend.py actuator script


import RPi.GPIO as GPIO
import time
# CHECK wires at RPi header for loose connections when problems occur
# HIGH is low and LOW is high in GPIO using the RPi.GPIO library

# ADD PWM
# 35 seconds is the actuator run time from beginning to end.

# Initialize software and hardware
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(26,GPIO.OUT)
GPIO.setup(19,GPIO.OUT)
GPIO.setup(13,GPIO.OUT)
GPIO.setup(6,GPIO.OUT)
# Shut all relays off. Relays are usually off on power up.
GPIO.output(26,GPIO.HIGH)
GPIO.output(19,GPIO.HIGH)
GPIO.output(13,GPIO.HIGH)
GPIO.output(6,GPIO.HIGH)
print('Initialized.')


#####################
# Do this at the end of the day, at 6:00 PM
#Extend on 12 seconds
#Extend on
GPIO.output(13,GPIO.LOW)
GPIO.output(6,GPIO.LOW)
print('Extending...')
time.sleep(16)
#Extend off
GPIO.output(13,GPIO.HIGH)
GPIO.output(6,GPIO.HIGH)
print('Extension done.')

Relay actuator control, sensor development

The relays mentioned earlier are to be connected to the RPi using a screw-down type connector mounted on the relay card. The original header will be removed. A ribbon cable with stackable header will be mounted on the RPi GPIO header. The RTC will 'stack' on top of the headers pins, 1,3,5,7,9. The ribbon cable will be cut and the selected wires attached to the relau card using the screw down connector. Ordinary breadboarding connector wires were used but proved too unreliable.
Intermittent connections caused problems.


The controller script will be in python language.

Currently there are two scripts, s-extend.py and s-retract.py.

The extend script extends the actuator for 17 seconds. The script is run twice each day, once in mid-morning, oonce in the afternoon.

The retract script is run once each day at the end of each day and runs the amount of time of the sum of the two extend scripts, or approximately 34 seconds.

-----------------------------------------------------

The sensor has been mounted on the array. Currently, the sensor is on the pipe with the array. The sensor will be mounted on a stationary point to maintain the same position with respect to the sun.
A new mounting mechanism is needed. The aluminum strips are too flexible.

The wires have been connected to the sensor and run into the house and to the staion.
Each wire has a different color piece of heatshrink tubing for identification.

A PCF8591 will be used to read the data. The PCF8591 card is mounted on the master breadboard, as is the RPi.

A buck voltage converter is also mounted on the master board. This will convert the battery bank 24vdc to 5vdc for the Raspberry Pi. The connection between the supply and the RPi is a mini-USB connector matching the socket on the RPi.


Raspberry Pi SoC installation script

This documents the procedure for installing the operating system and additional modifications on a Raspberry Pi. The current operating system is Raspbian Stretch, a variant of Debian 9 Stretch.
When viewing in a notepad with language highlighting, specify the script as Python in language.
--------------------------------------------------------------------------------------------------------------------



#========================  NOTES  ===========================
"""
Check VOM for current measurement. No current is read on 2mA scale with 3 digits (N.NN)

tightvnc is installed on the older SD card and RealVNC is on the newer SD card

create 'ssh' file in boot root while in Windows
Due to problems with the installation of hostapd and dnsmasq 'empty filename' error,
compilation of the Epever driver is done last.

Currently, both .102 and .103 IPs are accessible.

If the time is wrong in a ssh sessionusing RPI's wifi, ntp will auto-correct as soon as an internet connection is made.
At this point (completed installation 5-6-2018, ntp is included in Stretch and will update the hardwasre clock automatically if an internet connection is available.

NOTE: when trying to copy to 'html' with www-dat ownership, A saw the 'empty filename' raspberrypi-kernel-headers error message. Those headers were never installed. The driver copied to the /home/pi/ directory, froma different SD card, works.

The RPi will break connections with a laptop on its onw wifi, if a router wifi becomes available. Example: If I'm running an ssh session from my laptop, over CD2G-a, the RPi will break connection if I boot the router and modem.
"""

#Today, 5-6-18, did sudo systemctl start/enable EpeverX-hdr.service successfully.
#No header was being written to the data file, but the resources subdirectory had not been copied to the RPi.

sudo ifconfig
192.168.0.102 : ethernet (LAN) address.
192.168.0.103 : WIFI address.

ping raspberrypi
#C:\Users\jimjulian>ping raspberrypi.msnethome
#Pinging raspberrypi.msnethome [198.105.244.24] with 32 bytes of data:
#Request timed out.


#TODO:
#Modification s/w: if the day's data file has already been written and the RPi rebooted, do not write another header line to the file.

#Modification s/w: edit relay controls for environmental state determination & response.

#Modification s/w: write python code for solar sensor array.
#Modification h/w: hook up solar sensor to RPi. The PCF8951 will be the converter.

#Options: insert current resistors and ADS115s for power sensors.
#Remove thermal sensor from PCF3231 and attach to heat sensitive device, e.x. power supply unit or RPi.

#Check for automated downloads and instalations using the -Y option.

#    "sudo apt install apache2 apache2-utils -y"

#==================== END NOTES  ========================================
"""
Changed config
expand memory -- option: after saving an image of the completed installation.
change password 'passwd Newton'
changed timezone, localization.
-----------------------------------
Set DNS servers
"""

sudo nano /etc/network/interfaces
#added
nameservers 208.67.220.220 208.67.222.222
#to the interfaces file.

sudo nano /etc/resolv.conf
#added:
nameserver 208.67.220.220
nameserver 208.67.222.222
#-----------------------------------


#Default python is 2.7
#Install 3.6
sudo apt-get update
sudo apt-get install build-essential tk-dev libncurses5-dev libncursesw5-dev libreadline6-dev libdb5.3-dev libgdbm-dev libsqlite3-dev libssl-dev libbz2-dev libexpat1-dev liblzma-dev zlib1g-dev
Is the -Y option available for apt-get?

# https://www.python.org/downloads/source/ - latest version of Python
wget https://www.python.org/ftp/python/3.6.5/Python-3.6.5.tar.xz
tar xf Python-3.6.5.tar.xz
cd Python-3.6.5
./configure
make
sudo make altinstall

sudo apt-get install python3-pip

#From Tutorials.com
##sudo rm -r Python-3.6.0 <-- remove previous user-installed versions
rm Python-3.6.5.tar.xz
sudo apt-get --purge remove build-essential tk-dev
sudo apt-get --purge remove libncurses5-dev libncursesw5-dev libreadline6-dev
sudo apt-get --purge remove libdb5.3-dev libgdbm-dev libsqlite3-dev libssl-dev
sudo apt-get --purge remove libbz2-dev libexpat1-dev liblzma-dev zlib1g-dev


#=======================  RealVNC ==============================
# VNC:
# RealVNC is included in the Stretch distribution.



#========================================================================
#--------------------------------------------------------------------

# RPi.GPIO is integrated into the Stretch distribution.



#================== pigpio  ====================
"""
pigpio has a built in daemon.
A service file can be written for scripts using RPI.GPIO <<----------------<<<<<

wget abyz.co.uk/rpi/pigpio/pigpio.zip
unzip pigpio.zip
cd PIGPIO
make
sudo make install
Test
The Python module requires the services of the pigpio daemon. As a quick test. Start the daemon.
sudo pigpiod
Start Python.
python
NOTE: the following code is legacy. The start method is deprecated. The owner website is archaic and not updated.
Enter the following code (you can cut & paste but do not use the SELECT ALL button as that corrupts the formatting).
import pigpio
pigpio.start()
for g in range(0,32):
   print('gpio {} is {}'.format(g, pigpio.read(g))) # May need double quotes here.
pigpio.stop()
The code prints the level of the first 32 gpios.
To exit Python type exit() or ctrl-D.
A script to show the status of the first 32 gpios with updates is at http://abyz.co.uk/rpi/pigpio/code/gpio_status_py.zip.
END NOTE

UPDATED TEST CODE
#!/usr/bin/env python
import pigpio
pi = pigpio.pi() # connect to Pi
if not pi.connected:
   exit()
for g in range(0,32):
  print('gpio {} is {}'.format(g, pi.read(g)))       # May need double quotes here.
pi.stop() # disconnect from Pi

FROM WEB (with modifications)
#!/usr/bin/env python
# sets GPIO 7 high, then low and
# prints each change to the screen
import pigpio
pi = pigpio.pi() # connect to Pi
if not pi.connected:
   exit()
pi.write(7,1) # set GPIO 7 high
level = pi.read(7) # read GPIO 7
print(level)
pi.write(7,0)  # setr GPIO 7 low
level = pi.read(7) # read GPIO 7
print(level)
pi.stop() # disconnect from Pi
"""
#================= END pigpio  ====================

#-----------------------------------------------
# LAMP stack
sudo apt install apache2 apache2-utils -y
systemctl status apache2
#if not running, already, :
systemctl start apache2
#For authentication, choose'pi' over 'root'. The default password is 'raspberry'.

# Apache, Python, MySQL, and so on.
#apt-get install -y runs with automatic yes to prompts.
# FROM: https://www.linuxbabe.com/debian/install-lamp-stack-debian-9-stretch--
sudo apt-get install apache2 apache2-utils -y
systemctl status apache2
#If it’s not running, use systemctl to start it.
sudo systemctl start apache2
#It’s also a good idea to enable Apache to automatically start at boot time.
sudo systemctl enable apache2
#Check Apache version:
sudo apache2 -v
#Get RPi IP

sudo apt install curl
curl http://icanhazip.com
24.158.81.79
curl 127.0.0.1
#Result is typing the 'index.html' file to the screen.

sudo chown www-data:www-data /var/www/html/ -R
# Had to change this back to 'pi' to copy files to the directory.

sudo apt install mariadb-server mariadb-client # (drop-in replacement for MySQL)
sudo apt install mysql-server mysql-client
systemctl status mariadb
#If it’s not running, start it with this command:
sudo systemctl start mariadb
#To enable MariaDB to automatically start at boot time, run
sudo systemctl enable mariadb
#Now run the post installation security script.
sudo mysql_secure_installation
#When it asks you to enter MariaDB root password, press Enter key as the root password isn’t set yet. Then enter y to set the root password for MariaDB server.
#Next, you can just press Enter to answer all remaining questions. This will remove anonymous user, disable remote root login and remove
#test database. This step is a basic requirement for MariaDB database security.
#Now you can use the following command to log in to MariaDB server.
sudo mariadb -u root
#To exit, run
exit;
#Check MariaDB server version information.
mariadb --version
#PHP
sudo apt install php7.0 libapache2-mod-php7.0 php7.0-mysql php-common php7.0-cli php7.0-common php7.0-json php7.0-opcache php7.0-readline
#Enable the Apache php7.0 module then restart Apache Web server.
sudo a2enmod php7.0
sudo systemctl restart apache2
#Check PHP version information.
php --version
#To test PHP scripts with Apache server, we need to create a info.php file in the Web root directory.
sudo nano /var/www/html/info.php
#Paste the following PHP code into the file.
#<?php phpinfo(); ?>
#Save and close the file. Now in the browser address bar, enter server-ip-address/info.php. Replace sever-ip-address with your actual #IP. #If you follow this tutorial on your local computer, then type 127.0.0.1/info.php or localhost/info.php.
#You should see your server’s PHP information. This means PHP scripts can run properly with Apache web server. You can find that Zend #OPcache is enabled.
cd /var/www/html
cd../
sudo chown pi html
cd html
sudo chown pi index.html
rm index.html
#Edit the name of index.html yo _index.html.
#Open browser at RPi IP. click php file. Should list data.
#-------------------------------------------------
pip install pysolar
pip install pyephem

sudo apt-get install i2c-tools
sudo i2cdetect -y 1
sudo pip install pyephem
sudo pip install pysolar - optional
sudo apt-get autoremove
sudo apt-get install tightvncserver
sudo apt-get install pi-bluetooth
(already installed)
sudo apt-get install bluez bluez-firmware
sudo apt-get install blueman
bluetoothctl --help
git clone https://github.com/adafruit/Adafruit_Python_ADS1x15.git
cd Adafruit_Python_ADS1x15
sudo python setup.py install
# (python 2.7 was used)
#( was installed in current directory: /var/www/html/rersources/Adafruit_Python_ADS1x15/)
#--------------------------------------------------------------------------------
#===============================================================================


#===============  Set Ethernet Address  ========================
sudo ifconfig
sudo cp /etc/dhcpcd.conf /etc/dhcdcp.backup
sudo nano /etc/dhcpcd.conf

#Place these lines at the top of the file too set the Ethernet port (eth0) to a static IP address:
interface eth0
static ip_address=10.11.44.124/24
static routers=10.11.44.1
static domain_name_servers=172.16.33.85

#Set the address (ip_address) to the IP address you want the Raspberry Pi to occupy.
#Set the routers value to the gateway address
#If available, set to domain_name_servers to you name servers
#Once the file has been updated, use ctrl x to save and exit.
#Use the "ping" command to confirm that the Raspberry Pi is on the network
#and talking to another computer also on the network.

#If you have trouble pinging other computers on the network work, check the following:
#1. Confirm that the ethernet cable is firmly connected to the Raspberry Pi and network switch.
#2. Confirm that the ip address, mask and gateway are correct.
#3. If pinging a Windows machine, sometimes security setting prevent responding to a ping request.

#================================================================

#============ BEGIN ACCESS POINT  ===============
# RPi as access point.
#Instalation of hostapdf and dnsmasq are an opportunity to set the fixed IP of the RPi to that set in the router.
192.168.0.103
# This may not be a good idea. When the RPi wifii is beiong used, the 192 series may not be available, or conflict with MS Windows.


#RPI wifi access point

sudo apt-get update
sudo apt-get upgrade
#Install all the required software in one go with this command:
sudo apt-get install dnsmasq hostapd

#Since the configuration files are not ready yet, turn the new software off as follows:
sudo systemctl stop dnsmasq
sudo systemctl stop hostapd

#To configure a static IP address, edit the dhcpcd configuration file with:
sudo nano /etc/dhcpcd.conf

#Go to the end of the file and edit it so that it looks like the following:
interface wlan0
#    static ip_address=192.168.0.103/24
    static ip_address=172.24.1.1/24

#Now restart the dhcpcd daemon and set up the new `wlan0` configuration:
sudo service dhcpcd restart

#Configuring the DHCP server (dnsmasq)
#The DHCP service is provided by dnsmasq. By default, the configuration file contains a lot #of information that is not needed, and it is easier to start from scratch. Rename this #configuration file, and edit a new one:

sudo mv /etc/dnsmasq.conf /etc/dnsmasq.conf.orig 
sudo nano /etc/dnsmasq.conf
#Type or copy the following information into the dnsmasq configuration file and save it:

# Edited jlj
interface=wlan0      # Use the require wireless interface - usually wlan0
#  dhcp-range=192.168.0.2,192.168.0.200,255.255.255.0,24h
# Try this with 172.24.1.1
  dhcp-range=172.24.1.1,172.24.0.200,255.255.255.0,24h


#Configuring the access point host software (hostapd)
#You need to edit the hostapd configuration file, located at /etc/hostapd/hostapd.conf, to add the various parameters for your wireless network. After initial install, this will be a new/empty file.

sudo nano /etc/hostapd/hostapd.conf


#Add the information below to the configuration file. This configuration assumes we are using channel 7, with a network name of NameOfNetwork, and a password AardvarkBadgerHedgehog. Note that the name and password should not have quotes around them.

interface=wlan0
driver=nl80211
ssid=CD2G-a
hw_mode=g
channel=7
wmm_enabled=0
macaddr_acl=0
auth_algs=1
ignore_broadcast_ssid=0
wpa=2
wpa_passphrase=rxplc22549-a
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP
rsn_pairwise=CCMP


#We now need to tell the system where to find this configuration file.

sudo nano /etc/default/hostapd
#Find the line with #DAEMON_CONF, and replace it with this:
DAEMON_CONF="/etc/hostapd/hostapd.conf"

#Start it up
#Now start up the remaining services:
sudo service hostapd start 
sudo service dnsmasq start 
#Add routing and masquerade
#Edit /etc/sysctl.conf and uncomment this line:
net.ipv4.ip_forward=1
sudo nano /etc/sysctl.conf

#Add a masquerade for outbound traffic on eth0:
sudo iptables -t nat -A  POSTROUTING -o eth0 -j MASQUERADE

#Save the iptables rule.
sudo sh -c "iptables-save > /etc/iptables.ipv4.nat"

#Edit /etc/rc.local and add this just above "exit 0" to install these rules on boot.
iptables-restore < /etc/iptables.ipv4.nat

#++++++++++++++++++++Internet Access++++++++++++++++++
'''To get internet access, add the following step:
Step 8: Enable internet connection
Now the Raspberry Pi is acting as an access point to which other devices can connect. However, those devices can’t use the Pi to access the internet just yet. To make the possible, we need to build a bridge that will pass all traffic between the wlan0 and eth0 interfaces.
'''
#To build the bridge, let’s install one more package:
sudo apt-get install bridge-utils
#We’re ready to add a new bridge (called br0):
sudo brctl addbr br0
#Next, we’ll connect the eth0 interface to our bridge:
sudo brctl addif br0 eth0
#Finally, let’s edit the interfaces file:
sudo nano /etc/network/interfaces
#…and add the following lines at the end of the file:
auto br0
iface br0 inet manual
bridge_ports eth0 wlan0
#++++++++++++++++++++++++++++++++++++++++++++++++++++++

sudo reboot

#============ END ACCESS POINT  ===============



#===================================================================================
#PhpEpsolarTracer library -  this is the data collector.
#https://github.com/notro/rpi-source/wiki
#( part of the PHPepsolar togio installation that required recompilation of the Linux kernals)
#("getInfoData() function not returning info for Tracer Model A, here's the fix. · Issue #4 · #toggio/PhpEpsolarTracer · GitHub")

sudo apt-get install raspberrypi-kernel-headers
sudo apt-get install --reinstall raspberrypi-kernel-headers


#Files from RPi snapshots will already have needed changes made.
#===================================================================================
'''
The previous instructions:
1. sudo wget https://raw.githubusercontent.com/notro/rpi-source/master/rpi-source -O /usr/bin/rpi-source && sudo chmod +x /usr/bin/rpi-source && /usr/bin/rpi-source -q --tag-update
2. rpi-source

EPsolar-Tracer
https://github.com/kasbert/epsolar-tracer
This library uses python and is not used but includes the Tracer driver source code and instruction on installation.
Install the new headers from the web.

copy eps directory and go into xr_usb subdirectory. Type "make".
sudo insmod ./xr_usb_serial_common.ko
* Ensure that thecdc-acm module is not loaded (assumig that it is not needed)
# echo blacklist cdc-acm > /etc/modprobe.d/blacklist-cdc-acm.conf
# update-initramfs -u
lsusb
ls /dev/tty*
sudo rmmod cdc-acm
sudo modprobe -r usbserial
sudo reboot
FROM NOTES:
To remove the CDC-ACM driver and install the driver:
# rmmod cdc-acm
# modprobe -r usbserial
# modprobe usbserial
# insmod ./xr_usb_serial_common.ko
Better yet, examine or run epdriver.sh in /home/pi/.
Copy /var/www/html/ files from snapshot to RPi.
Run the client.php as a test of the Epsolar driver.
'''
Run epdriver.sh :
sudo rmmod cdc-acm
sudo insmod /home/pi/xr_usb_serial_common.ko

All that remains is the installation of service files.
Copy files to proper directory, /lib/systemd/system/.
From that directory
sudo cp /home/pi/epdriver.service epdriver.service
sudo cp /home/pi/EpeverX.service EpeverX.service
sudo cp /home/pi/EpeverX-hdr.service EpeverX-hdr.service

sudo systemctl start EpeverX.service
sudo systemctl enable EpeverX.service

sudo systemctl start EpeverX-hdr.service
sudo systemctl enable EpeverX-hdr.service

sudo systemctl start epdriver.service
sudo systemctl enable epdriver.service
# I got the script service running on boot, but failed 'start', yet passed 'enable'.

#NOTES: problems. EpeverX ran immediately. After some time, epdriver ran.
#Make sure the driver has not been loaded manually, when starting.

#//////////////////////////
# The RTC may need to be installed before hwclock is accessible.
#--------------------------------------
# The Stretch os has timedatectl.
# The change to EDT is also made by the timezone edit  using raspi-config.

timedatectl set-local-rtc 0 # for UTC
timedatectl set-local-rtc 1 # for EDT
timedatectl set-ntp true    # enable ntp
timedatectl set-ntp false   # disable ntp

timedatectl status
      Local time: Mon 2018-05-07 11:26:20 EDT
  Universal time: Mon 2018-05-07 15:26:20 UTC
        RTC time: Mon 2018-05-07 15:26:20
       Time zone: US/Eastern (EDT, -0400)
 Network time on: yes
NTP synchronized: yes
 RTC in local TZ: no

#Read clock
#To check the current system clock time (presented both in local time and UTC) as well as the RTC (hardware clock):
 timedatectl
#Set system clock
#To set the local time of the system clock directly:
 timedatectl set-time "yyyy-MM-dd hh:mm:ss"
#For example:
 timedatectl set-time "2014-05-26 11:13:54"

# timezone
America/New_York
--------------------------------------


sudo nano /boot/config.txt
add: dtoverlay=i2c-rtc,ds3231
sudo nano /lib/udev/hwclock-set
and comment out the following lines (using the #)

if [ -e /run/systemd/system ] ; then
   exit 0
fi

It’s also a good idea to comment out all the –systz lines too (as shown below). These update the RTC from the RPi and can cause issues.

fi
if [ yes - "$BADYEAR" ] ; then
#  /sbin/hwclock --rtc=$dev --systz --badyear
  /sbin/hwclock --rtc=$dev --hctosys --badyear
else
#  /sbin/hwclock --rtc=$dev --systz --badyear
  /sbin/hwclock --rtc=$dev --hctosys
fi

then exit and save (Ctrl-X then y). This will stop that script exiting early and will update the clock on boot.
Next reboot and the configuration is done.
i2cdetect -y 1
#RTC Clock: '68' at 68x8
# In this case, as in others, following the installation of the RTC, the '68' becomes a 'UU'.

#============================================================
#============================================================
#Note: ntp may already be installed in Stretch.
sudo apt-get install ntp
#============================================================
#RTC On Stretch
#from:
#https://www.raspberrypi.org/forums/viewtopic.php?t=209700
sudo nano /boot/config.txt
#add
dtparam=i2c_arm=on
dtoverlay=i2c-rtc,ds3231

sudo hwclock --systohc
May need to add the -w switch
sudo hwclock -w --systohc

sudo apt-get purge fake-hwclock

sudo nano /etc/udev/rules.d/85-hwclock.rules
add
# On the Raspberry Pi the RTC isn't available when systemd tries,
# set the time from RTC now when it is available.
KERNEL=="rtc0", RUN+="/sbin/hwclock --rtc=$root/$name --hctosys"

#Done.
#-----------------------------------------------
#Date and hwclock may report in UTC.
#Run raspi-config and set localization to U.S.
#UTF-8 may be an option.

#============================================================
#============================================================

#//////////////////////////
#EpeverX and epdriver services are installed. EpeverX-hdr is not. The php file does work.
#Make sure the PHP designation in the service files reflects one of the links in the /usr/bin/directory. PHP7.0 replaces PHP5.


#==========================================================================
#For an alternative access to the Tracer:
pip3 install pymodbus <-- did not work.
pip install pymodbus <-- worked
sudo pip3 install pymodbus
sudo pip install pymodbus

run stackexchange.py
NOTE: sometimes python/pip will not produce an error is sudo is needed but not used.
sudo pip install adafruit-ads1x15
#==================================================


sudo apt-get autoremove
sudo apt-get clean



# Best for the end of installations:
sudo apt-get autoremove
sudo apt-get clean


-------------------------------------------------------------------------------

Sunday, April 29, 2018

Actuator Control


   The linear actuator I've installed is working.
   The task now, is to develop the control system for the actuator.
   Long ago, I laid out  the basic plan to include software/Raspberry Pi computer and relaycontrol of the actuator. The relay board consists of eight relays  which can be controlled using the GPIO pins of the RPi (Raspberry Pi). Four of the ralays are setup to switch the power lines for motor reversal. This requires two relays acting as DPDT switched for one motor direction and a similar set for the reverse direction.
I have made wiring modificsations to the relay board and connected the board to the RPi using ribbon cable. I will have installed the library needed to run GPIO control commands from the RPi.
I first examined the PIGPIO library but had some segmentation faults with the daemon. This may be a result of SD card data corruption from an earlier system crash.
   I'm reformatting the SD card to eliminate that possibility. I have tentatively decided to use the RPi.GPIO library which was designed specifically for GPIO control. I may return to PIGPIO since some of the PWM routines I want to use, employ that library.
   I ran across an article on the web discussing the shortcomings of most PWM efforts with the RPi.
The auhtor also presented a solution that represents an improvement on those existing methods.
   I will try to find the saved article or the online webpage.
   The actuator requires a 20:1 rest:run ratio. For each minute of runtime, there needs to be 20 minutes of rest time. PWM will achieve two things. First,I'll be able to reduce the effects of a power surge when turning the actuator by using a vasrying duty cycle PWM wave with the power supply. Seconbd, the rest time can be incorporated into the duty cycle, in part, or in whole, to reduce the rest time, if needed.
   Eventually, I will have a separate battery/panel/inverter/contoller for the RPi's permanent use.
The RPi will run 24 hours per day but be in a sleep mode between 6PM and 6AM.
   Software routines will be written to use data from a calcultion and a sensor,to detrmine states and times for the panels' position. An example is the detection of cloudy and overcast days. The sensor will aid in the detection of fallen snow.
   The sensor can be calibrated and used to validate ephemeris calculations.


Monday, March 5, 2018

System File 5: A python script to calculate solar position



 A python script to calculate solar position without use of ephemeris library.
The script is imperfect. When the sun goes down, the position coordinates become imaginary numbers. Imaginary numbers are part of high level mathematics and not necessary for this project but are a default numerical type when certain conditions are present.
I may return to using an ephemeris library if the errors become unacceptable.

CODE
#NOAA Solar Calculations spreadsheet, Day

import math
import datetime
pi=3.14159
r=360/2/pi
B3=36.3 # Lat
B4=-82.2 # Lon
B5=TZ=-5 # time zone
#B not used
B7=11/26/2017
Y=datetime.datetime.now().year
M=datetime.datetime.now().month
D=datetime.datetime.now().day
H2="Blank"
# UTC-5=EDT
UTclock=datetime.datetime.utcnow().strftime("%H:%M:%S %Z")
LTclock=datetime.datetime.now().strftime("%H:%M:%S")
(hh, mm, ss)=UTclock.split(':')
UT=(int(hh)*3600+int(mm)*60+int(ss))/3600
LT=UT+TZ
h=datetime.datetime.now().hour
m=datetime.datetime.now().minute
s=datetime.datetime.now().second
if h > 12:
h=h-12
time=(int(h)*3600+int(m)*60+int(s))/3600
#Converting string into datetime
from datetime import datetime
datetime_object = datetime.strptime('Jun 1 2005  1:33PM', '%b %d %Y %I:%M%p')
# forward and reverse transformation
JD=(367 * Y ) - (int(7 * (Y + int((M + 9) / 12)) / 4)) + (int(275 * M / 9) + D + 1721013.5) + (UT / 24)
UTx=24 * ( JD + (int(7 * (Y + int((M + 9) / 12)) / 4)) - (int(275 * M / 9) + D + 1721013.5) - (367 * Y ) )
D2=int(JD)
E2=LT/24
F2=JD
#G=Julian Century
G2=(F2-2451545)/36525
#H=blank
#I=Geom Mean Long Sun#I2(1)=math.mod(280.46646+G2*(36000.76983+G2*0.0003032),360)
I2a=(280.46646+G2*(36000.76983+G2*0.0003032))
I2b=360
I2=I2a-int(I2a/I2b)*I2b
#J=Geometric Mean Anomaly of the Sun
J2=357.52911+G2*(35999.05029-0.0001537*G2)
#K=Eccentricity of Earth orbit
K2=0.016708634-G2*(0.000042037+0.0000001267*G2)
L2=math.sin(J2/r)*(1.914602-G2*(0.004817+0.000014*G2))+math.sin(2*J2/r)*(0.019993-0.000101*G2)+math.sin(3*J2/r)*0.000289
#M=Sun True Long degrees
M2=I2+L2
#N=Sun True Anomaly degrees
N2=J2+L2
#O=Sun Radius Vector, A.U.
O2=(1.000001018*(1-K2*K2))/(1+K2*math.cos(N2))
#P=Sun Apparent Long
P2=M2-0.00569-0.00478*math.sin(125.04-1934.136*G2)
#Q=Mean Oblique Ecliptic degrees (23.44)
Q2=23+(26+((21.448-G2*(46.815+G2*(0.00059-G2*0.001813))))/60)/60
#R=Oblique Correction factor (23.44)
R2=Q2+0.00256*math.cos((125.04-1934.136*G2)/r) # new
#S=Right Ascension degrees (120.74)
S2=math.atan2(math.cos(R2/r)*math.sin(P2/r), math.cos(P2/r))*r
T2=math.asin(math.sin(R2/r)*math.sin(P2/r))*r
#U=var y (0.04)
U2=math.tan(R2/2/r)*math.tan(R2/2/r)
#V=EoT minutes (13.55)
V2=4*(U2*math.sin(2*I2/r)-2*K2*math.sin(J2/r)+4*K2*U2*math.sin(J2/r)*math.cos(2*I2/r)-0.5*U2*U2*math.sin(4*I2/r)-1.25*K2*math.sin(2*J2/r))*r
V2=4*(U2*math.sin(2*(I2/r))-2*K2*math.sin((J2/r))+4*K2*U2*math.sin((J2/r))*math.cos(2*(I2/r))-0.5*U2*U2*math.sin(4*(I2/r))-1.25*K2*K2*math.sin(2*(J2/r)))*r
#W=HA Sunrise degrees (75.24)
W2=(math.acos(math.cos(90.833/r)/(math.cos(B3/r)*math.cos(T2/r))-math.tan(B3/r)*math.tan(T2/r)))*r#X=Sun noon LST (0.51)
X2=(720-4*B4-V2+B5*60)/1440
#Y=Sunrise time (0.3)
Y2=X2-W2*4/1440
#Z=Sunset time (0.72)
Z2=X2+W2*4/1440
#AA2=sunlight duration (601.9)
AA2=8*W2
#AB2=TST (404.75)
AB2a=(E2*1440+V2+4*B4-60*B5)
AB2b=1440
AB2=AB2a-int(AB2a/AB2b)*AB2b
if AB2/4 < 0 : AC2=AB2/4+180
else: AC2=AB2/4-180
#AD2=Zenith (93.46)
AD2=math.acos(math.sin(B3/r)*math.sin(T2/r)+math.cos(B3/r)*math.cos(T2/r)*math.cos(AC2/r))*r
#AE2= Sun elevation in degrees (-3.46)
AE2=90-AD2
#AF2=Atmospheric refraction in degrees (0.1)
if AE2>85 : AF2=0
elif AE2>5: AF2=58.1/math.tan((AE2))-0.07/math.pow(math.tan((AE2)),3)+0.000086/math.pow(math.tan((AE2)),5)
elif AE2>-0.575: AF2=1735+AE2*(-518.2+AE2*(103.4+AE2*(-12.79+AE2*0.711)))
else : AF2=-20.772/math.tan(AE2)/3600
 #AG2=Sun Elevation corrected for refraction (-3.37)
AG2=AE2+AF2
#AH2=Sun Azimuth degrees clockwise from North (112.93)
AH2a1=math.acos(((math.sin((B3/r)) * math.cos((AD2/r))) - math.sin((T2/r))) / ((math.cos((B3/r)) * math.sin(AD2/r))))*r + 180
AH2b1=360
AH2a2=540-math.acos(((math.sin(B3/r)*math.cos(AD2/r))-math.sin(T2/r))/((math.cos(B3/r)*math.sin(AD2/r))))*r
AH2b2=AH2b1
if AC2 > 0 : AH2=AH2a1-int(AH2a1/AH2b1)*AH2b1
else : AH2=AH2a2-int(AH2a2/AH2b2)*AH2b2
# error compensation
#AH2=AH2+7
'''
print(Y2+",")
print(Z2,",")
print(AE2,",")
print(AH2,",")
'''
#print (str(X2)+","+str(Y2)+","+str(AE2)+","+str(AH2));
ae2=str(AE2)
ah2=str(AH2)
#=============================================================================
# Si, Sm calculations
r=360/2/3.14159
a=0.14
h=0.535
ah=a*h
alpha=AE2 #40.5603 # Sel
beta=45
Z=90-alpha
psi=180
theta=AH2 #175.9508 # Saz

#AM=1/math.cos(Z/r) #  theta is 90-Sel or 90-alpha - use Z
#for flat earth, no earth curvature
AM=1/(math.cos(Z/r)+0.50572*pow(96.07995-Z/r,-1.6364))

# flat earth, no terrestrial elevation
#Si=1.353*math.pow(0.7,math.pow(AM,0.678))
Si=1.353*((1-ah)*pow(0.7,pow(AM,0.678))+ah)
Sm=Si*(math.cos(alpha/r)*math.sin(beta/r)*math.cos((psi-theta)/r)+math.sin(alpha/r)*math.cos(beta/r))
####################################################################################

print(str(ae2)+','+str(ah2)+','+str(Si)+','+str(Sm));
END CODE

System File 4: A javascript to handle date format differences between programming languages.

This java script makes sure the date is correctly interpreted between PHP and HTML. I found this on the web:

CODE
//<script>
/**
 * Return a formated string from a date Object mimicking PHP's date() functionality
 * format  string  "Y-m-d H:i:s" or similar PHP-style date format string
 * date    mixed   Date Object, Datestring, or milliseconds
 *
 * d-m-Y with leading zeroes
 * j-n-Y without leading zeroes
 *
 * dateFormat(d-m-Y, date), ex. date = 2-2-2017, and get 02-02-2017
 */
function dateFormat(format,date){
if(!date || date === "")
{ date = new Date();}
else if(typeof('date') !== 'object')
{date = new Date(date.replace(/-/g,"/")); // attempt to convert string to date object }
var string = '',
mo = date.getMonth(),   // month (0-11)
m1 = mo+1;     // month (1-12)
dow = date.getDay(),    // day of week (0-6)
d = date.getDate(),     // day of the month (1-31)
y = date.getFullYear(), // 1999 or 2003
h = date.getHours(),    // hour (0-23)
mi = date.getMinutes(), // minute (0-59)
s = date.getSeconds();  // seconds (0-59)
for (var i = 0, len = format.length; i < len; i++) {
switch(format[i])
{
case 'j': // Day of the month without leading zeros  (1 to 31)
string+= d;
break;
case 'd': // Day of the month, 2 digits WITH LEADING ZEROS (01 to 31)
string+= (d < 10) ? "0"+d : d;
break;
case 'm': // Numeric representation of a month, WITH LEADING ZEROS (01 to 12)
string+= (m1 < 10) ? "0"+m1 : m1;
break;
case 'n': // Numeric representation of a month, without leading zeros (1 to 12)
string+= m1;
break;
case 'Y': // A full numeric representation of a year, 4 digits (1999 OR 2003)
string+= y;
break;
default:
string+= format[i];
}
}
return string;
}
}
//</script>
END CODE

System File 3: HTML file to make an internet accessible real-time graph of panel activity


This file is a web page that graphs the current accumulated data for the day:

CODE
<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="refresh" content="300" />
  <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  <meta name="robots" content="noindex, nofollow">
  <meta name="googlebot" content="noindex, nofollow">
<script type="text/javascript" src="./resources/dateFormatscript.js"></script>
<script type="text/javascript" src="./resources/d3.v3.min.js"></script>
<script type="text/javascript" src="./resources/c3.js"></script>
<link rel="stylesheet" type="text/css" href="./resources/c3.css">
<style type="text/css"></style>
<title>once again</title>
<script type='text/javascript'>//<![CDATA[
window.onload=function(){
var d = new Date();
$d = (d.getMonth()+1) + '-' + d.getDate()+ '-' + d.getFullYear();
$de = 'data_' + dateFormat('m-d-Y',$d)+'.txt';
$df = dateFormat('m-d-Y',$d);

d3.csv($de)
.row(function(d) { return [d.time12, d.PVpower, d.BattSOC, d.elevcalc, d.azicalc]; })
.get(function(error,rows) {
rows.unshift (["time12","PVpower","BattSOC","elevcalc","azicalc"])
console.log(rows);
$c = new Date().getFullYear();
$a = new Date().getMonth() + 1;
$b = new Date().getUTCDate();
$d2 =  $df;
var chart = c3.generate({
title: {
text: $d2
},
  size:{
width: 1000,
height: 400
},
bindto: '#chart',
data: {
rows: rows,
type: 'line',
x: 'time12',
xFormat:'%I:%M:%S %p'
          },
point: {show: false},
tooltip: {show: false},
axis: {
x: {
localtime: true,
type:'timeseries',
tick:{
//culling:{max: 50},
fit: true,
count: 50,
format: '%I:%M:%S %p',
rotate: 65,
  }//end tick
},//end x

y: {
max: 350,
min: 0
} //end y
},//end axis
grid:{
x:{
show: true
},//end x
y:{
show: true
  }//end y
}//end grid
      });
});
}//]]>
</script>
</head>
<body>
  <div id="chart"></div>
<script>
  if (window.parent && window.parent.parent){
    window.parent.parent.postMessage(["resultsFrame", {
      height: document.body.getBoundingClientRect().height,
      slug: "None"
    }], "*")
  }
</script>
</body>
</html>
END CODE

System File 2:PHP script to write CSV header

File to write the CSV file header once each day or turn on cycle:

CODE
<?php
/*   epoutX-write-header.php   */

error_reporting(0);

exec ('sudo hwclock > /var/www/html/_hwc_out.txt');
exec ('date > /var/www/html/_date_out.txt');
exec ('sudo hwclock -w');

#$file= 'data_'.date('m-d-Y').'.txt'
$myfile = fopen('/var/www/html/data_'.date('m-d-Y').'.txt', "a") or die("Unable to open file!");
#shell_exec ( string 'sudo chown pi  $file'  )
fwrite($myfile,"time,time12,date,PV array voltage(V),PV array current(A),PVpower,Battery voltage(V),Battery charging current(A),Battery charging power(W),BattSOC,elevcalc,azicalc,Si,Sm\n");
fclose($myfile);

exec ('/bin/bash /var/www/html/epoutX-unlock_files.sh');



#$myfile = fopen('/var/www/html/data_XXX'.date('m-d-Y').'.txt', "a") or die("Unable to open file!");
#fwrite($myfile,"time,time12,date,PV array voltage(V),PV array current(A),PVpower,Battery voltage(V),Battery charging current(A),Battery charging power(W),BattSOC,azimuth,elevation\n");
#fclose($myfile);


?>
END CODE

System File 1:Data saver PHP script

 
   I'm publishing the files I've created to run and monitor, my system. There will be no explanations. I

The file to load and save data from the MPPT controller:

CODE
<?php
/*   epoutX-2.php   */
#date_default_timezone_set('EST');
#exec ('/bin/bash /var/www/html/epoutX-unlock_files.sh');

#$x=0;
require_once 'PhpEpsolarTracer.php';
$tracer = new PhpEpsolarTracer('/dev/ttyXRUSB0');
error_reporting(0);


$y = 1;
$x = 3;
#######################################
# exec ('/bin/bash /var/www/html/chd.sh');
#######################################

while($x = 3):
#######################################
exec ('/bin/bash /var/www/html/example_web.sh');
#######################################








#while($x=3):
$myfile = fopen('/var/www/html/data_'.date('m-d-Y').'.txt', "a") or die("Unable to open file!");
#If  ($y = 1){
# fwrite($myfile,"time,time12,date,PV array voltage(V),PV array current(A),PVpower,Battery voltage(V),Battery charging current(A),Battery charging power(W),BattSOC,azimuth,elevation,Si,Sm\n");
# $y = 0;
#  }


$nano = time_nanosleep(30, 0);
  if ($tracer->getRealtimeData()) {
    $i=0;
#--------------------------------------->
    $pythonnoaaephem = `/usr/bin/env python3.6 /var/www/html/resources/NOAA.py`;

#____________________________________


    $date=date("Y-m-d H:i:s");
    $seconds = strtotime($date);
    $seconds /= 30;
    $seconds = round($seconds);
    $seconds *= 30;
    $date2 = date("h:i:s", $seconds);
    $date = date("h:i:s A", $seconds);
    $today = date("Y-m-d"); # Y-m-d
    $now = $date;
#______________________________________
    fwrite($myfile, $date2);
    fwrite($myfile, ",");
    fwrite($myfile, $now);
    fwrite($myfile, ",");
    fwrite($myfile, $today.",");
#---------------------------------------->
    while ($i<=5):
      $dat[$i] = $tracer->realtimeData[$i].",";
       fwrite($myfile, $dat[$i]);
       $i++;
    endwhile;
  $i=12;
$dat[$i] = $tracer->realtimeData[$i].",";
    fwrite($myfile, $dat[$i]);

    }
#--------------------------------------------------------->
    fwrite($myfile,$pythonnoaaephem);
#--------------------------------------------------------->





endwhile;
    fclose($myfile);
?>
END CODE

Update and plans for CGI model of shadows



This post, I'm laying out plans to construct an animation of my property and the shadows cast throughout the year. I also recap progress on the installation.
   This will allow me to determine the best location for my array, or whether I will need to move the array, at least once per  year.

   The software I'll be using is Pov-Ray (Point of View Raytracer). If possible and necesasary, I'll use the architectural raytracer, Radiance.

   I have the formulae I need to do the calculations for solar positioning throughout the year. I'll get terrain data from D.E.M. data provided by the government for free. I also have twenty years of CDs containing GIS data and software to fall back on.
  The D.E.M. (Digital Elevation Map) is a file containing elevation data for points on an area of terrain. Generally, a seven degree quadrangle is the unit of measure. One 'quad' will contain data points similar to the pixels in an image file. The difference is the image data represents color or grayscale values. In fact, I have converted DEM files into grayscale high dynamic range images for use in rendering engines (raytracers). I constructed an animated gif of a local quad from topographic map graphic layers and a DEM layer. The gif shows the flat topo map flat, then the DEM data 'pushing' through from under to create a 3D map with a topo map overlay.

   I may use the Moray 3D object editing software to construct geometric tree and house objects to cast shadows. Some have created tree files for use in populating a landscape in Pov-Ray. I may use one of those.

   I've determined I need to double the number of watts for a comfortable minimum power for the system. A factor of two compensates for days that are overcast. There have to be more watts (panels) or more batteries. The panels last longer than batteries and are less expensive in terms of usage. Batteries last about five years. Panels have an industry wide warranty of twenty years for 80% rating.
   There is a balance between the number of batteries and panels.  Extra batteries are needed to draw only 50% of available power. The general rule for lead acid deep cycle batteries is: use no more than 50% to preserve longevity.

   There is one alternative to moving the array around. Find a way to get the owner of the adjoining property to remove or lower the top level of the evergreen trees blocking the sunlight from my array in the winter months.

   I may take that option. Roof mount would be an option if the roof were slanted more South. The roof points 20 degrees East of South. I would need to build a stage to position the aray pointing South. That is too difficult and costly. I don't like the idea of modifying my roof, either.

   That is the end of this post.

New webpage and chart(s)

  The new page has two charts, one above the other. There are links to a copy of my old website, a more touchscreen friendly version of the ...