Skip to main content

FLL EV3 Robot

This blog post is about our current EV3 robot we're planning to use in the 2023/2024 FLL competition. Some features: 2 large motors for steering. 2 medium motors for attachments.  2 colour sensors for picking up the white and black lines, also used for line squaring. 1 gyro sensor. To enable attachments to be changed as quickly as possible we're using gravity to keep the gears connected, i.e. you don't need to fasten anything to the robot. Every attachment has 2x 12 tooth double bevel gear (part 32270) which comes in contact with the 2x 20 tooth double bevel gears (part 32269) on the robot. The medium motors are horizontally aligned on the robots, but we use 12 tooth double bevel gears to convert that to vertical alignments. These in turn are connected to 20 tooth double bevel gears, and the attachments in turn connect to these 20 tooth double bevel gears with their 12 tooth double bevel gears.  The complete robot is modelled in Bricklink Studio 2 . You can download the rob

OpenWRT 3G connection checker & logger

A 3G connection is normally not very stable - so we need something to periodically check it & reconnect when needed. I also wanted a summary email at the end of each day with the total traffic per client. I'm using the following settings/scripts:

Edit /etc/crontabs/root (create if not existing):

# send stats & disconnect 3G at 23:00 everyday.
# check the connection every 5 minutes between 5:00 and 23:00 and reconnect if needed
# reboot at 5:00 if /tmp/stats.msg doesn't exist - will be sent in checkconnect
*/5 5-22 * * * /usr/bin/checkconnection
0 5 * * * if [ ! -s /tmp/stats.msg ]; then reboot ; fi
0 23 * * * /usr/bin/sendstats && ifdown wan

The first line will run /usr/bin/checkconnection every 5 minutes between 5:00 and 22:59. Then at 23:00 the  day's statistics will be emailed and the 3G connection disconnected. The next morning at 5:00 it first checks if the email was sucessfully sent at 23:00, if so it will reboot the router (seems to be more stable if you reboot it every day), and part of the reboot will be to enable the 3G connection. If the email was not sent, checkconnection will reopen the connection and try to re-send. On success it will reboot the router.

The router automatically updates the date & time with a NTP server. Make sure you have the correct  timezone defined in /etc/config/system.

The scripts:
/usr/bin/checkconnection: It first updates the 3g stats. Then if we have an email to be sent, we first send it (replace from@addres.com with your from address, to@address.com with your to address and smtp.com with your smtp server):

# write 3g stats to logfile
/usr/bin/wrtbwmon setup 3g-wan
/usr/bin/wrtbwmon update /tmp/log/wrtbwmon
# try to send out email if it's still pending
if [ -s /tmp/stats.msg ];
then
  cat /tmp/stats.msg | mini_sendmail -ffrom@address.com -ssmtp.com to@address.com
  if [ $? -eq 0 ] ; then reboot ; fi
fi
# if 3g is connected, we have nothing to do
if
  ifconfig 3g-wan
  then
  # sometimes ifconfig 3g-wan shows information, but 3g-wan is not running
  if
    ifconfig | grep 3g-wan
    then
      exit 0
  fi
  # if we reach this, it means we need to restart 3g-wan
  ifdown wan
fi
# if we get to this point, it means 3g is not connected
# check if we can access /dev/ttyUSB2 - if not reset the USB device
# and reconnect
if [ -e /dev/ttyUSB2 ];
then
  ifup wan
else
  /usr/bin/usb_modeswitch -c /etc/usb_modeswitch.d/custom
  sleep 10
  ifup wan
fi
/etc/usb_modeswitch.d/custom: It seems usb_modeswitch does not always recognise the USB modem, so we need sometimes need to no manually do a modeswitch. This is for a Huawei E1752 - search the web for other modems:

DefaultVendor=0x12d1
DefaultProduct=0x1446
TargetVendor=0x12d1
TargetProdct=0x1001
MessageEndpoint=0x01
MessageContent="55534243000000000000000000000011060000000000000000000000000000"


/usr/bin/wrtbwmon: This was originally taken from http://code.google.com/p/wrtbwmon/ and modified to suit my needs.

#!/bin/sh
#
# Traffic logging tool for OpenWRT-based routers
#
# Created by Emmanuel Brucy (e.brucy AT qut.edu.au)
#
# Based on work from Fredrik Erlandsson (erlis AT linux.nu)
# Based on traff_graph script by twist - http://wiki.openwrt.org/RrdTrafficWatch
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
LAN_IFACE=${2} || $(nvram get lan_ifname)
lock()
{
        while [ -f /tmp/wrtbwmon.lock ]; do
                if [ ! -d /proc/$(cat /tmp/wrtbwmon.lock) ]; then
                        echo "WARNING : Lockfile detected but process $(cat /tmp/wrtbwmon.lock) does not exist !"
                        rm -f /tmp/wrtbwmon.lock
                fi
                sleep 1
        done
        echo $$ > /tmp/wrtbwmon.lock
}
unlock()
{
        rm -f /tmp/wrtbwmon.lock
}
case ${1} in
"setup" )
        #Create the RRDIPT CHAIN (it doesn't matter if it already exists).
        iptables -N RRDIPT 2> /dev/null
        #Add the RRDIPT CHAIN to the FORWARD chain (if non existing).
        iptables -L FORWARD --line-numbers -n | grep "RRDIPT" | grep "1" > /dev/null
        if [ $? -ne 0 ]; then
                iptables -L FORWARD -n | grep "RRDIPT" > /dev/null
                if [ $? -eq 0 ]; then
                        echo "DEBUG : iptables chain misplaced, recreating it..."
                        iptables -D FORWARD -j RRDIPT
                fi
                iptables -I FORWARD -j RRDIPT
        fi
        #For each host in the ARP table
        grep 192.168.1 /proc/net/arp | while read IP TYPE FLAGS MAC MASK IFACE ;
        do
                #Add iptable rules (if non existing).
                iptables -nL RRDIPT | grep "${IP} " > /dev/null
                if [ $? -ne 0 ]; then
                        echo "DEBUG : adding rule for IP ${IP}"
                        iptables -I RRDIPT -d ${IP} -j RETURN -i ${2}
                        iptables -I RRDIPT -s ${IP} -j RETURN -o ${2}
                fi
        done
        ;;
"update" )
        [ -z "${2}" ] && echo "ERROR : Missing argument 2" && exit 1
        # Uncomment this line if you want to abort if database not found
        # [ -f "${2}" ] || exit 1
        # Create an empty file if not existing
        [ -f "${2}" ] || touch ${2}
        lock
        #Read and reset counters
        iptables -L RRDIPT -vnxZ -t filter > /tmp/traffic_$$.tmp
        grep -v "0x0" /proc/net/arp | grep -v 'IP address' | grep -v eth0.1 | while read IP TYPE FLAGS MAC MASK IFACE
        do
                #Add new data to the graph. Count in Kbs to deal with 16 bits signed values (up to 2G only)
                #Have to use temporary files because of crappy busybox shell
                grep ${IP} /tmp/traffic_$$.tmp | while read PKTS BYTES TARGET PROT OPT IFIN IFOUT SRC DST
                do
                        [ "${DST}" = "${IP}" ] && echo $((${BYTES}/1000)) > /tmp/in_$$.tmp
                        [ "${SRC}" = "${IP}" ] && echo $((${BYTES}/1000)) > /tmp/out_$$.tmp
                done
                IN=$(cat /tmp/in_$$.tmp)
                OUT=$(cat /tmp/out_$$.tmp)
                rm -f /tmp/in_$$.tmp
                rm -f /tmp/out_$$.tmp
                if [ ${IN} -gt 0 -o ${OUT} -gt 0 ];  then
                        echo "DEBUG : New traffic for ${MAC} since last update : ${IN}k:${OUT}k"
                        LINE=$(grep ${MAC} ${2})
                        if [ -z "${LINE}" ]; then
                                echo "DEBUG : ${MAC} is a new host !"
                                PEAKUSAGE_IN=0
                                PEAKUSAGE_OUT=0
                                OFFPEAKUSAGE_IN=0
                                OFFPEAKUSAGE_OUT=0
                        else
                                PEAKUSAGE_IN=$(echo ${LINE} | cut -f2 -s -d, )
                                PEAKUSAGE_OUT=$(echo ${LINE} | cut -f3 -s -d, )
                                OFFPEAKUSAGE_IN=$(echo ${LINE} | cut -f4 -s -d, )
                                OFFPEAKUSAGE_OUT=$(echo ${LINE} | cut -f5 -s -d, )
                        fi
                        if [ "${3}" = "offpeak" ]; then
                                OFFPEAKUSAGE_IN=$((${OFFPEAKUSAGE_IN}+${IN}))
                                OFFPEAKUSAGE_OUT=$((${OFFPEAKUSAGE_OUT}+${OUT}))
                        else
                                PEAKUSAGE_IN=$((${PEAKUSAGE_IN}+${IN}))
                                PEAKUSAGE_OUT=$((${PEAKUSAGE_OUT}+${OUT}))
                        fi
                        grep -v "${MAC}" ${2} > /tmp/db_$$.tmp
                        mv /tmp/db_$$.tmp ${2}
                        echo ${MAC},${PEAKUSAGE_IN},${PEAKUSAGE_OUT},${OFFPEAKUSAGE_IN},${OFFPEAKUSAGE_OUT},$(date "+%d-%m-%Y %H:%M") >> ${2}
                fi
        done
        #Free some memory
        rm -f /tmp/*_$$.tmp
        unlock
        ;;
"publish" )
        [ -z "${2}" ] && echo "ERROR : Missing argument 2" && exit 1
        [ -z "${3}" ] && echo "ERROR : Missing argument 3" && exit 1
        USERSFILE="/etc/dnsmasq.conf"
        [ -f "${USERSFILE}" ] || USERSFILE="/tmp/dnsmasq.conf"
        [ -z "${4}" ] || USERSFILE=${4}
        [ -f "${USERSFILE}" ] || USERSFILE="/dev/null"
        # first do some number crunching - rewrite the database so that it is sorted
        lock
        mkdir -p /tmp/www
        touch /tmp/sorted_$$.tmp
        cat ${2} | while IFS=, read MAC PEAKUSAGE_IN PEAKUSAGE_OUT OFFPEAKUSAGE_IN OFFPEAKUSAGE_OUT LASTSEEN
        do
                echo ${PEAKUSAGE_IN},${PEAKUSAGE_OUT},${OFFPEAKUSAGE_IN},${OFFPEAKUSAGE_OUT},${MAC},${LASTSEEN} >> /tmp/sorted_$$.tmp
        done
        unlock
        # create HTML page
        echo "Traffic

Total Usage :

" >> ${3}
        echo "" >> ${3}
        echo "
UserPeak downloadPeak uploadOffpeak downloadOffpeak uploadLast seen
" >> ${3}
        echo "
This page was generated on `date`" 2>&1 >> ${3}
        echo "" >> ${3}
        #Free some memory
        rm -f /tmp/*_$$.tmp
        ;;
*)
        echo "Usage : $0 {setup|update|publish} [options...]"
        echo "Options : "
        echo "   $0 setup"
        echo "   $0 update database_file [offpeak]"
        echo "   $0 publish database_file path_of_html_report [user_file]"
        echo "Examples : "
        echo "   $0 setup"
        echo "   $0 update /tmp/usage.db offpeak"
        echo "   $0 publish /tmp/usage.db /www/user/usage.htm /jffs/users.txt"
        echo "Note : [user_file] is an optional file to match users with their MAC address"
        echo "       Its format is : 00:MA:CA:DD:RE:SS,username , with one entry per line"
        exit
        ;;
esac
/usr/bin/sendstats: Replace from@address.com with your from address, to@addres.com with your to address, and smtp.com with your smtp server.

echo "From: OpenWRT router " > /tmp/stats.msg
echo "To: to@address.com" >> /tmp/stats.msg
echo "Subject: Router statistics" >> /tmp/stats.msg
echo "" >> /tmp/stats.msg
echo "Uptime:" >> /tmp/stats.msg
uptime >> /tmp/stats.msg
echo "" >> /tmp/stats.msg
echo "wrtbwmon:" >> /tmp/stats.msg
cat /tmp/log/wrtbwmon >> /tmp/stats.msg
echo "" >> /tmp/stats.msg
echo "PPP log:" >> /tmp/stats.msg
cat /var/log/ppp >> /tmp/stats.msg
echo "" >> /tmp/stats.msg
#echo "/proc/net/arp:" >> /tmp/stats.msg
#cat /proc/net/arp >> /tmp/stats.msg
#echo "" >> /tmp/stats.msg
echo "ifconfig:" >> /tmp/stats.msg
ifconfig >> /tmp/stats.msg
echo "" >> /tmp/stats.msg
#echo "logread:" >> /tmp/stats.msg
#logread >> /tmp/stats.msg
rm /tmp/log/wrtbwmon
rm /var/log/ppp
cat /tmp/stats.msg | mini_sendmail -ffrom@address.com -ssmtp.com to@address.com
if [ $? -eq 0 ] ; then rm /tmp/stats.msg ; fi
/etc/ppp/ip-up.d/3glog: (everytime the 3g connects, write the date & time to a log file)

#!/bin/sh
logfile=/var/log/ppp
echo "`date` Connected $0 $1 $2 $3 $4 $5 $6" >> $logfile
# setup bandwidth monitoring
/usr/bin/wrtbwmon setup 3g-wan


/etc/ppp/ip-down.d/3glog: (everytime the 3g disconnects, write the date & time & total bytes sent to a log file)

#!/bin/sh
logfile=/var/log/ppp
echo "`date` Disconnected $0 $1 $2 $3 $4 $5 $6" >> $logfile
logread | tail | grep Sent >> $logfile


Comments

Popular posts from this blog

Installing Lego Digital Designer (LDD) on Windows 10

If you're using Windows 10 18.09 or later and try to install Lego Digital Designer (LDD) 4.3.11 you'll probably get an installation error for Adobe Flash Player. However, there is an easy way around it: Download the installation file for LDD 4.3.11. Rename the .exe file to .zip. If you don't see the .exe extension in Explorer, go to "View - Options" on the Explorer menu, then under the "View" tab deselect the "Hide extensions for known file types". Open the zip file with Windows Explorer. Copy all files in the zip to another directory on your computer. In the new folder: Delete install_flash_player_active_x.exe. Copy OpenGLChecker.exe and rename it to install_flash_player_active_x.exe. Run LDDSetup.exe. In short the installer will execute install_flash_player_active_x.exe during the installation process, but all it does now is to execute the same logic as what OpenGLChecker does. In theory you can run any .exe that will not retu

Windows Hyper-V Server 2019

This post will explain how to use the free Hyper-V Windows 2019 Server version. This version doesn't come with any GUI interface as provided in the full Windows 2019 Server version. Instead it comes with a character interface, but with the help of some third party tools you can easily get a fully functional Hyper-V server for free. The following will be assumed: You have a dedicated server connected to a network and you want to install Hyper-V 2019 on this server to run Virtual Machines and/or act as a file server. You have physical access to this server to do the installation. You have another machine connected to the same network to do remote management, running a recent version of Microsoft Windows. You don't want to join a domain or use Active Directory. You can do this if you want to, but this is not included in this post. First you'll need to download the Hyper-V 2019 ISO from  https://www.microsoft.com/en-us/evalcenter/evaluate-hyper-v-server-2019 . You’ll