Unneeded code
This commit is contained in:
1
setup.py
1
setup.py
@@ -19,7 +19,6 @@ setup(
|
|||||||
packages=[
|
packages=[
|
||||||
'bbctrl',
|
'bbctrl',
|
||||||
'inevent',
|
'inevent',
|
||||||
'lcd',
|
|
||||||
'camotics',
|
'camotics',
|
||||||
'iw_parse'
|
'iw_parse'
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -1,143 +0,0 @@
|
|||||||
/******************************************************************************\
|
|
||||||
|
|
||||||
This file is part of the Buildbotics firmware.
|
|
||||||
|
|
||||||
Copyright (c) 2015 - 2018, Buildbotics LLC
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
This file ("the software") is free software: you can redistribute it
|
|
||||||
and/or modify it under the terms of the GNU General Public License,
|
|
||||||
version 2 as published by the Free Software Foundation. You should
|
|
||||||
have received a copy of the GNU General Public License, version 2
|
|
||||||
along with the software. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
The software 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
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with the software. If not, see
|
|
||||||
<http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
For information regarding this software email:
|
|
||||||
"Joseph Coffland" <joseph@buildbotics.com>
|
|
||||||
|
|
||||||
\******************************************************************************/
|
|
||||||
|
|
||||||
#include "lcd.h"
|
|
||||||
#include "rtc.h"
|
|
||||||
#include "hardware.h"
|
|
||||||
#include "command.h"
|
|
||||||
|
|
||||||
#include <avr/io.h>
|
|
||||||
#include <avr/wdt.h>
|
|
||||||
#include <util/delay.h>
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
|
|
||||||
void lcd_init(uint8_t addr) {
|
|
||||||
// Enable I2C master
|
|
||||||
TWIC.MASTER.BAUD = F_CPU / 2 / 100000 - 5; // 100 KHz
|
|
||||||
TWIC.MASTER.CTRLA = TWI_MASTER_ENABLE_bm;
|
|
||||||
TWIC.MASTER.CTRLB = TWI_MASTER_TIMEOUT_DISABLED_gc;
|
|
||||||
TWIC.MASTER.STATUS = TWI_MASTER_BUSSTATE_IDLE_gc;
|
|
||||||
|
|
||||||
_delay_ms(50);
|
|
||||||
lcd_nibble(addr, 3 << 4); // Home
|
|
||||||
_delay_ms(50);
|
|
||||||
lcd_nibble(addr, 3 << 4); // Home
|
|
||||||
_delay_ms(50);
|
|
||||||
lcd_nibble(addr, 3 << 4); // Home
|
|
||||||
lcd_nibble(addr, 2 << 4); // 4-bit
|
|
||||||
|
|
||||||
lcd_write(addr,
|
|
||||||
LCD_FUNCTION_SET | LCD_2_LINE | LCD_5x8_DOTS | LCD_4_BIT_MODE, 0);
|
|
||||||
lcd_write(addr, LCD_DISPLAY_CONTROL | LCD_DISPLAY_ON, 0);
|
|
||||||
lcd_write(addr, LCD_ENTRY_MODE_SET | LCD_ENTRY_SHIFT_INC, 0);
|
|
||||||
|
|
||||||
lcd_write(addr, LCD_CLEAR_DISPLAY, 0);
|
|
||||||
lcd_write(addr, LCD_RETURN_HOME, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void _master_wait() {
|
|
||||||
#ifdef __AVR__
|
|
||||||
while (!(TWIC.MASTER.STATUS & TWI_MASTER_WIF_bm)) continue;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void _write_i2c(uint8_t addr, uint8_t data) {
|
|
||||||
data |= BACKLIGHT_BIT;
|
|
||||||
|
|
||||||
TWIC.MASTER.ADDR = addr << 1;
|
|
||||||
_master_wait();
|
|
||||||
|
|
||||||
TWIC.MASTER.DATA = data;
|
|
||||||
_master_wait();
|
|
||||||
|
|
||||||
TWIC.MASTER.CTRLC = TWI_MASTER_CMD_STOP_gc;
|
|
||||||
|
|
||||||
_delay_us(100);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void lcd_nibble(uint8_t addr, uint8_t data) {
|
|
||||||
_write_i2c(addr, data);
|
|
||||||
_write_i2c(addr, data | ENABLE_BIT);
|
|
||||||
_delay_us(500);
|
|
||||||
_write_i2c(addr, data & ~ENABLE_BIT);
|
|
||||||
_delay_us(100);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void lcd_write(uint8_t addr, uint8_t cmd, uint8_t flags) {
|
|
||||||
lcd_nibble(addr, flags | (cmd & 0xf0));
|
|
||||||
lcd_nibble(addr, flags | ((cmd << 4) & 0xf0));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void lcd_goto(uint8_t addr, uint8_t x, uint8_t y) {
|
|
||||||
static uint8_t row[] = {0, 64, 20, 84};
|
|
||||||
lcd_write(addr, LCD_SET_DDRAM_ADDR | (row[y] + x), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void lcd_putchar(uint8_t addr, uint8_t c) {
|
|
||||||
lcd_write(addr, c, REG_SELECT_BIT);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void lcd_pgmstr(uint8_t addr, const char *s) {
|
|
||||||
while (true) {
|
|
||||||
char c = pgm_read_byte(s++);
|
|
||||||
if (!c) break;
|
|
||||||
lcd_putchar(addr, c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void _splash(uint8_t addr) {
|
|
||||||
lcd_init(addr);
|
|
||||||
lcd_goto(addr, 1, 1);
|
|
||||||
lcd_pgmstr(addr, PSTR("Controller booting"));
|
|
||||||
lcd_goto(addr, 3, 2);
|
|
||||||
lcd_pgmstr(addr, PSTR("Please wait..."));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void lcd_splash() {
|
|
||||||
wdt_disable();
|
|
||||||
_splash(0x27);
|
|
||||||
_splash(0x3f);
|
|
||||||
wdt_enable(WDTO_250MS);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void lcd_rtc_callback() {
|
|
||||||
// Display the splash if we haven't gotten any commands in 1sec since boot
|
|
||||||
if (!command_is_active() && rtc_get_time() == 1000)
|
|
||||||
lcd_splash();
|
|
||||||
}
|
|
||||||
@@ -1,103 +0,0 @@
|
|||||||
/******************************************************************************\
|
|
||||||
|
|
||||||
This file is part of the Buildbotics firmware.
|
|
||||||
|
|
||||||
Copyright (c) 2015 - 2018, Buildbotics LLC
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
This file ("the software") is free software: you can redistribute it
|
|
||||||
and/or modify it under the terms of the GNU General Public License,
|
|
||||||
version 2 as published by the Free Software Foundation. You should
|
|
||||||
have received a copy of the GNU General Public License, version 2
|
|
||||||
along with the software. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
The software 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
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with the software. If not, see
|
|
||||||
<http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
For information regarding this software email:
|
|
||||||
"Joseph Coffland" <joseph@buildbotics.com>
|
|
||||||
|
|
||||||
\******************************************************************************/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "pgmspace.h"
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
|
|
||||||
// Control flags
|
|
||||||
enum {
|
|
||||||
REG_SELECT_BIT = 1 << 0,
|
|
||||||
READ_BIT = 1 << 1,
|
|
||||||
ENABLE_BIT = 1 << 2,
|
|
||||||
BACKLIGHT_BIT = 1 << 3,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// Commands
|
|
||||||
enum {
|
|
||||||
LCD_CLEAR_DISPLAY = 1 << 0,
|
|
||||||
LCD_RETURN_HOME = 1 << 1,
|
|
||||||
LCD_ENTRY_MODE_SET = 1 << 2,
|
|
||||||
LCD_DISPLAY_CONTROL = 1 << 3,
|
|
||||||
LCD_CURSOR_SHIFT = 1 << 4,
|
|
||||||
LCD_FUNCTION_SET = 1 << 5,
|
|
||||||
LCD_SET_CGRAM_ADDR = 1 << 6,
|
|
||||||
LCD_SET_DDRAM_ADDR = 1 << 7,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// Entry Mode Set flags
|
|
||||||
#define LCD_ENTRY_SHIFT_DISPLAY (1 << 0)
|
|
||||||
#define LCD_ENTRY_SHIFT_INC (1 << 1)
|
|
||||||
#define LCD_ENTRY_SHIFT_DEC (0 << 1)
|
|
||||||
|
|
||||||
|
|
||||||
// Display Control flags
|
|
||||||
#define LCD_BLINK_ON (1 << 0)
|
|
||||||
#define LCD_BLINK_OFF (0 << 0)
|
|
||||||
#define LCD_CURSOR_ON (1 << 1)
|
|
||||||
#define LCD_CURSOR_OFF (0 << 1)
|
|
||||||
#define LCD_DISPLAY_ON (1 << 2)
|
|
||||||
#define LCD_DISPLAY_OFF (0 << 2)
|
|
||||||
|
|
||||||
|
|
||||||
// Cursor Shift flags
|
|
||||||
#define LCD_SHIFT_RIGHT (1 << 2)
|
|
||||||
#define LCD_SHIFT_LEFT (0 << 2)
|
|
||||||
#define LCD_SHIFT_DISPLAY (1 << 3)
|
|
||||||
#define LCD_SHIFT_CURSOR (0 << 3)
|
|
||||||
|
|
||||||
|
|
||||||
// Function Set flags
|
|
||||||
#define LCD_5x11_DOTS (1 << 2)
|
|
||||||
#define LCD_5x8_DOTS (0 << 2)
|
|
||||||
#define LCD_2_LINE (1 << 3)
|
|
||||||
#define LCD_1_LINE (0 << 3)
|
|
||||||
#define LCD_8_BIT_MODE (1 << 4)
|
|
||||||
#define LCD_4_BIT_MODE (0 << 4)
|
|
||||||
|
|
||||||
|
|
||||||
// Text justification flags
|
|
||||||
enum {
|
|
||||||
JUSTIFY_LEFT = 0,
|
|
||||||
JUSTIFY_RIGHT = 1,
|
|
||||||
JUSTIFY_CENTER = 2,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
void lcd_init(uint8_t addr);
|
|
||||||
void lcd_nibble(uint8_t addr, uint8_t data);
|
|
||||||
void lcd_write(uint8_t addr, uint8_t cmd, uint8_t flags);
|
|
||||||
void lcd_goto(uint8_t addr, uint8_t x, uint8_t y);
|
|
||||||
void lcd_putchar(uint8_t addr, uint8_t c);
|
|
||||||
void lcd_pgmstr(uint8_t addr, const char *s);
|
|
||||||
void lcd_splash();
|
|
||||||
void lcd_rtc_callback();
|
|
||||||
@@ -30,7 +30,6 @@
|
|||||||
#include "switch.h"
|
#include "switch.h"
|
||||||
#include "analog.h"
|
#include "analog.h"
|
||||||
#include "motor.h"
|
#include "motor.h"
|
||||||
#include "lcd.h"
|
|
||||||
#include "vfd_spindle.h"
|
#include "vfd_spindle.h"
|
||||||
|
|
||||||
#include <avr/io.h>
|
#include <avr/io.h>
|
||||||
@@ -46,7 +45,6 @@ static uint32_t ticks;
|
|||||||
ISR(RTC_OVF_vect) {
|
ISR(RTC_OVF_vect) {
|
||||||
ticks++;
|
ticks++;
|
||||||
|
|
||||||
lcd_rtc_callback();
|
|
||||||
switch_rtc_callback();
|
switch_rtc_callback();
|
||||||
analog_rtc_callback();
|
analog_rtc_callback();
|
||||||
vfd_spindle_rtc_callback();
|
vfd_spindle_rtc_callback();
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
# Makefile for Bulidbotics step-test
|
|
||||||
PROJECT = step-test
|
|
||||||
MCU = atxmega192a3u
|
|
||||||
CLOCK = 32000000
|
|
||||||
|
|
||||||
# SRC
|
|
||||||
SRC = usart.c lcd.c pins.c hardware.c
|
|
||||||
SRC := $(wildcard *.c) $(patsubst %,../src/%,$(SRC))
|
|
||||||
|
|
||||||
include ../Makefile.common
|
|
||||||
|
|
||||||
CFLAGS += -I../src -I.
|
|
||||||
|
|
||||||
# Build
|
|
||||||
all: $(PROJECT).hex size
|
|
||||||
|
|
||||||
$(PROJECT).elf: $(SRC)
|
|
||||||
$(CC) $(SRC) $(CFLAGS) $(LDFLAGS) $(LIBS) -o $@
|
|
||||||
|
|
||||||
.PHONY: all
|
|
||||||
@@ -1,187 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
################################################################################
|
|
||||||
# #
|
|
||||||
# This file is part of the Buildbotics firmware. #
|
|
||||||
# #
|
|
||||||
# Copyright (c) 2015 - 2018, Buildbotics LLC #
|
|
||||||
# All rights reserved. #
|
|
||||||
# #
|
|
||||||
# This file ("the software") is free software: you can redistribute it #
|
|
||||||
# and/or modify it under the terms of the GNU General Public License, #
|
|
||||||
# version 2 as published by the Free Software Foundation. You should #
|
|
||||||
# have received a copy of the GNU General Public License, version 2 #
|
|
||||||
# along with the software. If not, see <http://www.gnu.org/licenses/>. #
|
|
||||||
# #
|
|
||||||
# The software 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 #
|
|
||||||
# Lesser General Public License for more details. #
|
|
||||||
# #
|
|
||||||
# You should have received a copy of the GNU Lesser General Public #
|
|
||||||
# License along with the software. If not, see #
|
|
||||||
# <http://www.gnu.org/licenses/>. #
|
|
||||||
# #
|
|
||||||
# For information regarding this software email: #
|
|
||||||
# "Joseph Coffland" <joseph@buildbotics.com> #
|
|
||||||
# #
|
|
||||||
################################################################################
|
|
||||||
|
|
||||||
import sys, serial, argparse
|
|
||||||
import numpy as np
|
|
||||||
import math
|
|
||||||
import json
|
|
||||||
from time import sleep
|
|
||||||
from collections import deque
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
import matplotlib.pyplot as plt
|
|
||||||
import matplotlib.animation as animation
|
|
||||||
|
|
||||||
|
|
||||||
MM_PER_STEP = 5 * 1.8 / 360 / 32
|
|
||||||
SAMPLES_PER_MIN = 6000
|
|
||||||
|
|
||||||
|
|
||||||
class Plot:
|
|
||||||
def __init__(self, port, baud, max_len):
|
|
||||||
# Open serial port
|
|
||||||
self.sp = serial.Serial(port, baud)
|
|
||||||
|
|
||||||
# Create data series
|
|
||||||
self.series = []
|
|
||||||
for i in range(5):
|
|
||||||
self.series.append(deque([0.0] * max_len))
|
|
||||||
|
|
||||||
# Init vars
|
|
||||||
self.max_len = max_len
|
|
||||||
self.incoming = ''
|
|
||||||
self.last = [None] * 4
|
|
||||||
|
|
||||||
# Open velocity log
|
|
||||||
ts = datetime.now().strftime('%Y-%m-%d-%H:%M:%S')
|
|
||||||
self.log = open('velocity-%s.log' % ts, 'w')
|
|
||||||
|
|
||||||
|
|
||||||
# Add new series data
|
|
||||||
def add(self, i, value):
|
|
||||||
self.series[i].pop()
|
|
||||||
self.series[i].appendleft(value)
|
|
||||||
|
|
||||||
|
|
||||||
def update_text(self, text, vel, data):
|
|
||||||
text[4].set_text('V {0:8,.2f}'.format(vel))
|
|
||||||
|
|
||||||
for i in range(4):
|
|
||||||
text[i].set_text('{} {:11,}'.format('XYZA'[i], int(data[i])))
|
|
||||||
|
|
||||||
|
|
||||||
def update(self, frame, axes, text):
|
|
||||||
# Read new data
|
|
||||||
try:
|
|
||||||
data = self.sp.read(self.sp.in_waiting)
|
|
||||||
self.incoming += data.decode('utf-8')
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
print(e)
|
|
||||||
return
|
|
||||||
|
|
||||||
while True:
|
|
||||||
# Parse lines
|
|
||||||
i = self.incoming.find('\n')
|
|
||||||
if i == -1: break
|
|
||||||
line = self.incoming[0:i]
|
|
||||||
self.incoming = self.incoming[i + 1:]
|
|
||||||
|
|
||||||
# Handle reset
|
|
||||||
if line.find('RESET') != -1:
|
|
||||||
self.update_text(text, 0, [0] * 4)
|
|
||||||
self.log.write(line + '\n')
|
|
||||||
self.last = [None] * 4
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Parse data
|
|
||||||
try:
|
|
||||||
data = [float(value) for value in line.split(',')]
|
|
||||||
except ValueError: continue
|
|
||||||
|
|
||||||
if len(data) != 4: continue
|
|
||||||
|
|
||||||
# Compute axis velocities
|
|
||||||
v = [] # Axis velocity
|
|
||||||
totalV = 0 # Tool velocity
|
|
||||||
|
|
||||||
for i in range(4):
|
|
||||||
if self.last[i] is not None:
|
|
||||||
delta = self.last[i] - data[i]
|
|
||||||
v.append(delta * MM_PER_STEP * SAMPLES_PER_MIN) # mm/min
|
|
||||||
totalV += math.pow(v[i], 2)
|
|
||||||
|
|
||||||
self.last[i] = data[i]
|
|
||||||
|
|
||||||
# Compute tool velocity
|
|
||||||
totalV = math.sqrt(totalV)
|
|
||||||
|
|
||||||
# Update position and velocity text
|
|
||||||
self.update_text(text, totalV, data)
|
|
||||||
|
|
||||||
# Don't update plots when not moving
|
|
||||||
if totalV == 0: continue
|
|
||||||
|
|
||||||
# Add new data
|
|
||||||
for i in range(4): self.add(i, v[i])
|
|
||||||
self.add(4, totalV)
|
|
||||||
|
|
||||||
# Update plots
|
|
||||||
for i in range(5):
|
|
||||||
axes[i].set_data(range(self.max_len), self.series[i])
|
|
||||||
|
|
||||||
self.log.write(line + '\n')
|
|
||||||
|
|
||||||
|
|
||||||
def close(self):
|
|
||||||
self.sp.flush()
|
|
||||||
self.sp.close()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
# Parse command line arguments
|
|
||||||
description = "Plot velocity data in real-time"
|
|
||||||
parser = argparse.ArgumentParser(description = description)
|
|
||||||
parser.add_argument('-p', '--port', default = '/dev/ttyUSB0')
|
|
||||||
parser.add_argument('-b', '--baud', default = 115200, type = int)
|
|
||||||
parser.add_argument('-m', '--max-width', default = 2000, type = int)
|
|
||||||
args = parser.parse_args()
|
|
||||||
|
|
||||||
# Create plot
|
|
||||||
plot = Plot(args.port, args.baud, args.max_width)
|
|
||||||
fig = plt.figure()
|
|
||||||
ax = plt.axes(xlim = (0, args.max_width), ylim = (-10000, 10000))
|
|
||||||
axes = []
|
|
||||||
axes_text = []
|
|
||||||
|
|
||||||
# Setup position and velocity text fields
|
|
||||||
font = dict(fontsize = 14, family = 'monospace')
|
|
||||||
|
|
||||||
axes_text.append(plt.text(0, 11700, '', **font))
|
|
||||||
axes_text.append(plt.text(800, 11700, '', **font))
|
|
||||||
axes_text.append(plt.text(0, 10500, '', **font))
|
|
||||||
axes_text.append(plt.text(800, 10500, '', **font))
|
|
||||||
axes_text.append(plt.text(1500, 11700, '', **font))
|
|
||||||
|
|
||||||
# Create axes
|
|
||||||
for i in range(5):
|
|
||||||
axes.append(ax.plot([], [])[0])
|
|
||||||
# Set text color to match axis color
|
|
||||||
axes_text[i].set_color(axes[i].get_color())
|
|
||||||
|
|
||||||
# Initial text views
|
|
||||||
plot.update_text(axes_text, 0, [0] * 4)
|
|
||||||
|
|
||||||
# Set up animation
|
|
||||||
anim = animation.FuncAnimation(fig, plot.update, fargs = [axes, axes_text],
|
|
||||||
interval = 100)
|
|
||||||
|
|
||||||
# Run
|
|
||||||
plt.show()
|
|
||||||
plot.close()
|
|
||||||
@@ -1,230 +0,0 @@
|
|||||||
/******************************************************************************\
|
|
||||||
|
|
||||||
This file is part of the Buildbotics firmware.
|
|
||||||
|
|
||||||
Copyright (c) 2015 - 2018, Buildbotics LLC
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
This file ("the software") is free software: you can redistribute it
|
|
||||||
and/or modify it under the terms of the GNU General Public License,
|
|
||||||
version 2 as published by the Free Software Foundation. You should
|
|
||||||
have received a copy of the GNU General Public License, version 2
|
|
||||||
along with the software. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
The software 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
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with the software. If not, see
|
|
||||||
<http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
For information regarding this software email:
|
|
||||||
"Joseph Coffland" <joseph@buildbotics.com>
|
|
||||||
|
|
||||||
\******************************************************************************/
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
#include "hardware.h"
|
|
||||||
#include "usart.h"
|
|
||||||
#include "lcd.h"
|
|
||||||
|
|
||||||
#include <avr/interrupt.h>
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
|
|
||||||
#define RESET_PIN SPI_MOSI_PIN
|
|
||||||
|
|
||||||
|
|
||||||
void rtc_init() {}
|
|
||||||
|
|
||||||
|
|
||||||
static struct {
|
|
||||||
uint8_t step_pin;
|
|
||||||
uint8_t dir_pin;
|
|
||||||
TC0_t *timer;
|
|
||||||
volatile int16_t high;
|
|
||||||
volatile bool reading;
|
|
||||||
|
|
||||||
} channel[4] = {
|
|
||||||
{STEP_X_PIN, DIR_X_PIN, &TCC0, 0},
|
|
||||||
{STEP_Y_PIN, DIR_Y_PIN, &TCD0, 0},
|
|
||||||
{STEP_Z_PIN, DIR_Z_PIN, &TCE0, 0},
|
|
||||||
{STEP_A_PIN, DIR_A_PIN, &TCF0, 0},
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
static int reset = 0;
|
|
||||||
|
|
||||||
|
|
||||||
void channel_reset(int i) {channel[i].timer->CNT = channel[i].high = 0;}
|
|
||||||
|
|
||||||
|
|
||||||
#define EVSYS_CHMUX(CH) (&EVSYS_CH0MUX)[CH]
|
|
||||||
#define EVSYS_CHCTRL(CH) (&EVSYS_CH0CTRL)[CH]
|
|
||||||
|
|
||||||
|
|
||||||
void channel_overflow(int i) {
|
|
||||||
if (IN_PIN(channel[i].dir_pin)) channel[i].high--;
|
|
||||||
else channel[i].high++;
|
|
||||||
channel[i].reading = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ISR(TCC0_OVF_vect) {channel_overflow(0);}
|
|
||||||
ISR(TCD0_OVF_vect) {channel_overflow(1);}
|
|
||||||
ISR(TCE0_OVF_vect) {channel_overflow(2);}
|
|
||||||
ISR(TCF0_OVF_vect) {channel_overflow(3);}
|
|
||||||
|
|
||||||
|
|
||||||
void channel_update_dir(int i) {
|
|
||||||
if (IN_PIN(channel[i].dir_pin)) channel[i].timer->CTRLFSET = TC0_DIR_bm;
|
|
||||||
else channel[i].timer->CTRLFCLR = TC0_DIR_bm;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ISR(PORTE_INT0_vect) {for (int i = 0; i < 4; i++) channel_update_dir(i);}
|
|
||||||
|
|
||||||
|
|
||||||
int32_t __attribute__ ((noinline)) _channel_read(int i) {
|
|
||||||
return (int32_t)channel[i].high << 16 | channel[i].timer->CNT;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int32_t channel_read(int i) {
|
|
||||||
while (true) {
|
|
||||||
channel[i].reading = true;
|
|
||||||
|
|
||||||
int32_t x = _channel_read(i);
|
|
||||||
int32_t y = _channel_read(i);
|
|
||||||
|
|
||||||
if (x != y || !channel[i].reading) continue;
|
|
||||||
|
|
||||||
channel[i].reading = false;
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void channel_update_enable(int i) {
|
|
||||||
if (IN_PIN(MOTOR_ENABLE_PIN))
|
|
||||||
channel[i].timer->CTRLA = TC_CLKSEL_EVCH0_gc + i;
|
|
||||||
else channel[i].timer->CTRLA = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ISR(PORTF_INT0_vect) {
|
|
||||||
for (int i = 0; i < 4; i++) channel_update_enable(i);
|
|
||||||
if (!IN_PIN(MOTOR_ENABLE_PIN)) reset = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ISR(PORTC_INT0_vect) {reset = 32;}
|
|
||||||
|
|
||||||
|
|
||||||
ISR(TCC1_OVF_vect) {
|
|
||||||
if (reset) reset--;
|
|
||||||
|
|
||||||
// Report measured steps
|
|
||||||
static int32_t counts[4] = {0, 0, 0, 0};
|
|
||||||
bool moving = false;
|
|
||||||
bool zero = true;
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
int32_t count = channel_read(i);
|
|
||||||
if (count != counts[i]) moving = true;
|
|
||||||
if (count) zero = false;
|
|
||||||
counts[i] = count;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (reset && !zero) {
|
|
||||||
for (int i = 0; i < 4; i++) channel_reset(i);
|
|
||||||
printf("RESET\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (moving)
|
|
||||||
printf("%ld,%ld,%ld,%ld\n", counts[0], counts[1], counts[2], counts[3]);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void _splash(uint8_t addr) {
|
|
||||||
lcd_init(addr);
|
|
||||||
lcd_goto(addr, 5, 1);
|
|
||||||
lcd_pgmstr(addr, PSTR("Step Test"));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void channel_init(int i) {
|
|
||||||
uint8_t step_pin = channel[i].step_pin;
|
|
||||||
uint8_t dir_pin = channel[i].dir_pin;
|
|
||||||
|
|
||||||
// Configure I/O
|
|
||||||
DIRCLR_PIN(step_pin);
|
|
||||||
DIRCLR_PIN(dir_pin);
|
|
||||||
PINCTRL_PIN(step_pin) = PORT_SRLEN_bm | PORT_ISC_RISING_gc;
|
|
||||||
PINCTRL_PIN(dir_pin) = PORT_SRLEN_bm | PORT_ISC_BOTHEDGES_gc;
|
|
||||||
|
|
||||||
// Dir change interrupt
|
|
||||||
PIN_PORT(dir_pin)->INTCTRL |= PORT_INT0LVL_HI_gc;
|
|
||||||
PIN_PORT(dir_pin)->INT0MASK |= PIN_BM(dir_pin);
|
|
||||||
|
|
||||||
// Events
|
|
||||||
EVSYS_CHMUX(i) = PIN_EVSYS_CHMUX(step_pin);
|
|
||||||
EVSYS_CHCTRL(i) = EVSYS_DIGFILT_8SAMPLES_gc;
|
|
||||||
|
|
||||||
// Clock
|
|
||||||
channel_update_enable(i);
|
|
||||||
channel[i].timer->INTCTRLA = TC_OVFINTLVL_HI_gc;
|
|
||||||
|
|
||||||
// Set initial clock direction
|
|
||||||
channel_update_dir(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void init() {
|
|
||||||
cli();
|
|
||||||
|
|
||||||
hw_init();
|
|
||||||
usart_init();
|
|
||||||
|
|
||||||
// Motor channels
|
|
||||||
for (int i = 0; i < 4; i++) channel_init(i);
|
|
||||||
|
|
||||||
// Motor enable
|
|
||||||
DIRCLR_PIN(MOTOR_ENABLE_PIN);
|
|
||||||
PINCTRL_PIN(MOTOR_ENABLE_PIN) =
|
|
||||||
PORT_SRLEN_bm | PORT_ISC_BOTHEDGES_gc | PORT_OPC_PULLUP_gc;
|
|
||||||
PIN_PORT(MOTOR_ENABLE_PIN)->INTCTRL |= PORT_INT0LVL_HI_gc;
|
|
||||||
PIN_PORT(MOTOR_ENABLE_PIN)->INT0MASK |= PIN_BM(MOTOR_ENABLE_PIN);
|
|
||||||
|
|
||||||
// Configure report clock
|
|
||||||
TCC1.INTCTRLA = TC_OVFINTLVL_LO_gc;
|
|
||||||
TCC1.PER = F_CPU / 256 * 0.01; // 10ms
|
|
||||||
TCC1.CTRLA = TC_CLKSEL_DIV256_gc;
|
|
||||||
|
|
||||||
// Reset switch
|
|
||||||
DIRCLR_PIN(RESET_PIN);
|
|
||||||
PINCTRL_PIN(RESET_PIN) =
|
|
||||||
PORT_SRLEN_bm | PORT_ISC_RISING_gc | PORT_OPC_PULLUP_gc;
|
|
||||||
PIN_PORT(RESET_PIN)->INTCTRL |= PORT_INT0LVL_LO_gc;
|
|
||||||
PIN_PORT(RESET_PIN)->INT0MASK |= PIN_BM(RESET_PIN);
|
|
||||||
|
|
||||||
printf("RESET\n");
|
|
||||||
|
|
||||||
sei();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
init();
|
|
||||||
|
|
||||||
_splash(0x27);
|
|
||||||
_splash(0x3f);
|
|
||||||
|
|
||||||
while (true) continue;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@@ -31,7 +31,6 @@ class Ctrl(object):
|
|||||||
self.avr = bbctrl.AVR(self)
|
self.avr = bbctrl.AVR(self)
|
||||||
|
|
||||||
self.i2c = bbctrl.I2C(args.i2c_port, args.demo)
|
self.i2c = bbctrl.I2C(args.i2c_port, args.demo)
|
||||||
self.lcd = bbctrl.LCD(self)
|
|
||||||
self.mach = bbctrl.Mach(self, self.avr)
|
self.mach = bbctrl.Mach(self, self.avr)
|
||||||
self.preplanner = bbctrl.Preplanner(self)
|
self.preplanner = bbctrl.Preplanner(self)
|
||||||
if not args.demo:
|
if not args.demo:
|
||||||
@@ -40,9 +39,6 @@ class Ctrl(object):
|
|||||||
|
|
||||||
self.mach.connect()
|
self.mach.connect()
|
||||||
|
|
||||||
self.lcd.add_new_page(bbctrl.MainLCDPage(self))
|
|
||||||
self.lcd.add_new_page(bbctrl.IPLCDPage(self.lcd))
|
|
||||||
|
|
||||||
os.environ['GCODE_SCRIPT_PATH'] = self.get_upload()
|
os.environ['GCODE_SCRIPT_PATH'] = self.get_upload()
|
||||||
|
|
||||||
except Exception:
|
except Exception:
|
||||||
|
|||||||
@@ -1,48 +0,0 @@
|
|||||||
################################################################################
|
|
||||||
# #
|
|
||||||
# This file is part of the Buildbotics firmware. #
|
|
||||||
# #
|
|
||||||
# Copyright (c) 2015 - 2018, Buildbotics LLC #
|
|
||||||
# All rights reserved. #
|
|
||||||
# #
|
|
||||||
# This file ("the software") is free software: you can redistribute it #
|
|
||||||
# and/or modify it under the terms of the GNU General Public License, #
|
|
||||||
# version 2 as published by the Free Software Foundation. You should #
|
|
||||||
# have received a copy of the GNU General Public License, version 2 #
|
|
||||||
# along with the software. If not, see <http://www.gnu.org/licenses/>. #
|
|
||||||
# #
|
|
||||||
# The software 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 #
|
|
||||||
# Lesser General Public License for more details. #
|
|
||||||
# #
|
|
||||||
# You should have received a copy of the GNU Lesser General Public #
|
|
||||||
# License along with the software. If not, see #
|
|
||||||
# <http://www.gnu.org/licenses/>. #
|
|
||||||
# #
|
|
||||||
# For information regarding this software email: #
|
|
||||||
# "Joseph Coffland" <joseph@buildbotics.com> #
|
|
||||||
# #
|
|
||||||
################################################################################
|
|
||||||
|
|
||||||
import subprocess
|
|
||||||
|
|
||||||
import bbctrl
|
|
||||||
|
|
||||||
|
|
||||||
class IPLCDPage(bbctrl.LCDPage):
|
|
||||||
# From bbctrl.LCDPage
|
|
||||||
def activate(self):
|
|
||||||
p = subprocess.Popen(['hostname', '-I'], stdout = subprocess.PIPE)
|
|
||||||
ips = p.communicate()[0].decode('utf-8').split()
|
|
||||||
|
|
||||||
p = subprocess.Popen(['hostname'], stdout = subprocess.PIPE)
|
|
||||||
hostname = p.communicate()[0].decode('utf-8').strip()
|
|
||||||
|
|
||||||
self.clear()
|
|
||||||
|
|
||||||
self.text('Host: %s' % hostname[0:14], 0, 0)
|
|
||||||
|
|
||||||
for i in range(min(3, len(ips))):
|
|
||||||
if len(ips[i]) <= 16:
|
|
||||||
self.text('IP: %s' % ips[i], 0, i + 1)
|
|
||||||
@@ -64,12 +64,6 @@ class Jog(inevent.JogHandler):
|
|||||||
self.processor = inevent.InEvent(ctrl.ioloop, self, types = ['js'])
|
self.processor = inevent.InEvent(ctrl.ioloop, self, types = ['js'])
|
||||||
|
|
||||||
|
|
||||||
def up(self): self.ctrl.lcd.page_up()
|
|
||||||
def down(self): self.ctrl.lcd.page_down()
|
|
||||||
def left(self): self.ctrl.lcd.page_left()
|
|
||||||
def right(self): self.ctrl.lcd.page_right()
|
|
||||||
|
|
||||||
|
|
||||||
def callback(self):
|
def callback(self):
|
||||||
if self.v != self.lastV:
|
if self.v != self.lastV:
|
||||||
self.lastV = self.v
|
self.lastV = self.v
|
||||||
|
|||||||
@@ -1,207 +0,0 @@
|
|||||||
################################################################################
|
|
||||||
# #
|
|
||||||
# This file is part of the Buildbotics firmware. #
|
|
||||||
# #
|
|
||||||
# Copyright (c) 2015 - 2018, Buildbotics LLC #
|
|
||||||
# All rights reserved. #
|
|
||||||
# #
|
|
||||||
# This file ("the software") is free software: you can redistribute it #
|
|
||||||
# and/or modify it under the terms of the GNU General Public License, #
|
|
||||||
# version 2 as published by the Free Software Foundation. You should #
|
|
||||||
# have received a copy of the GNU General Public License, version 2 #
|
|
||||||
# along with the software. If not, see <http://www.gnu.org/licenses/>. #
|
|
||||||
# #
|
|
||||||
# The software 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 #
|
|
||||||
# Lesser General Public License for more details. #
|
|
||||||
# #
|
|
||||||
# You should have received a copy of the GNU Lesser General Public #
|
|
||||||
# License along with the software. If not, see #
|
|
||||||
# <http://www.gnu.org/licenses/>. #
|
|
||||||
# #
|
|
||||||
# For information regarding this software email: #
|
|
||||||
# "Joseph Coffland" <joseph@buildbotics.com> #
|
|
||||||
# #
|
|
||||||
################################################################################
|
|
||||||
|
|
||||||
import lcd
|
|
||||||
import atexit
|
|
||||||
|
|
||||||
|
|
||||||
class LCDPage:
|
|
||||||
def __init__(self, lcd, text = None):
|
|
||||||
self.lcd = lcd
|
|
||||||
self.data = lcd.new_screen()
|
|
||||||
|
|
||||||
if text is not None:
|
|
||||||
self.text(text, (lcd.width - len(text)) // 2, 1)
|
|
||||||
|
|
||||||
|
|
||||||
def activate(self): pass
|
|
||||||
def deactivate(self): pass
|
|
||||||
|
|
||||||
|
|
||||||
def put(self, c, x, y):
|
|
||||||
y += x // self.lcd.width
|
|
||||||
x %= self.lcd.width
|
|
||||||
y %= self.lcd.height
|
|
||||||
|
|
||||||
if self.data[x][y] != c:
|
|
||||||
self.data[x][y] = c
|
|
||||||
if self == self.lcd.page: self.lcd.update()
|
|
||||||
|
|
||||||
|
|
||||||
def text(self, s, x, y):
|
|
||||||
for c in s:
|
|
||||||
self.put(c, x, y)
|
|
||||||
x += 1
|
|
||||||
|
|
||||||
|
|
||||||
def clear(self):
|
|
||||||
self.data = self.lcd.new_screen()
|
|
||||||
self.lcd.redraw = True
|
|
||||||
|
|
||||||
|
|
||||||
def shift_left(self): pass
|
|
||||||
def shift_right(self): pass
|
|
||||||
def shift_up(self): pass
|
|
||||||
def shift_down(self): pass
|
|
||||||
|
|
||||||
|
|
||||||
class LCD:
|
|
||||||
def __init__(self, ctrl):
|
|
||||||
self.ctrl = ctrl
|
|
||||||
self.log = ctrl.log.get('LCD')
|
|
||||||
|
|
||||||
self.addrs = self.ctrl.args.lcd_addr
|
|
||||||
self.addr = self.addrs[0]
|
|
||||||
self.addr_num = 0
|
|
||||||
|
|
||||||
self.width = 20
|
|
||||||
self.height = 4
|
|
||||||
self.lcd = None
|
|
||||||
self.timeout = None
|
|
||||||
self.reset = False
|
|
||||||
self.page = None
|
|
||||||
self.pages = []
|
|
||||||
self.current_page = 0
|
|
||||||
self.screen = self.new_screen()
|
|
||||||
self.set_message('Loading...')
|
|
||||||
|
|
||||||
self._redraw(False)
|
|
||||||
if not ctrl.args.demo: atexit.register(self.goodbye)
|
|
||||||
|
|
||||||
|
|
||||||
def set_message(self, msg):
|
|
||||||
try:
|
|
||||||
self.load_page(LCDPage(self, msg))
|
|
||||||
self._update()
|
|
||||||
except IOError as e:
|
|
||||||
self.log.warning('LCD communication failed: %s' % e)
|
|
||||||
|
|
||||||
|
|
||||||
def new_screen(self):
|
|
||||||
return [[' ' for y in range(self.height)] for x in range(self.width)]
|
|
||||||
|
|
||||||
|
|
||||||
def new_page(self): return LCDPage(self)
|
|
||||||
def add_page(self, page): self.pages.append(page)
|
|
||||||
|
|
||||||
|
|
||||||
def add_new_page(self, page = None):
|
|
||||||
if page is None: page = self.new_page()
|
|
||||||
page.id = len(self.pages)
|
|
||||||
self.add_page(page)
|
|
||||||
return page
|
|
||||||
|
|
||||||
|
|
||||||
def load_page(self, page):
|
|
||||||
if self.page != page:
|
|
||||||
if self.page is not None: self.page.deactivate()
|
|
||||||
page.activate()
|
|
||||||
self.page = page
|
|
||||||
self.redraw = True
|
|
||||||
self.update()
|
|
||||||
|
|
||||||
|
|
||||||
def set_current_page(self, current_page):
|
|
||||||
self.current_page = current_page % len(self.pages)
|
|
||||||
self.load_page(self.pages[self.current_page])
|
|
||||||
|
|
||||||
|
|
||||||
def page_up(self): pass
|
|
||||||
def page_down(self): pass
|
|
||||||
def page_right(self): self.set_current_page(self.current_page + 1)
|
|
||||||
def page_left(self): self.set_current_page(self.current_page - 1)
|
|
||||||
|
|
||||||
|
|
||||||
def update(self):
|
|
||||||
if self.timeout is None:
|
|
||||||
self.timeout = self.ctrl.ioloop.call_later(0.25, self._update)
|
|
||||||
|
|
||||||
|
|
||||||
def _redraw(self, now = True):
|
|
||||||
if now:
|
|
||||||
self.redraw = True
|
|
||||||
self.update()
|
|
||||||
self.redraw_timer = self.ctrl.ioloop.call_later(5, self._redraw)
|
|
||||||
|
|
||||||
|
|
||||||
def _update(self):
|
|
||||||
self.timeout = None
|
|
||||||
|
|
||||||
try:
|
|
||||||
if self.lcd is None:
|
|
||||||
self.lcd = lcd.LCD(self.ctrl.i2c, self.addr, self.height,
|
|
||||||
self.width)
|
|
||||||
|
|
||||||
if self.reset:
|
|
||||||
self.lcd.reset()
|
|
||||||
self.redraw = True
|
|
||||||
self.reset = False
|
|
||||||
|
|
||||||
cursorX, cursorY = -1, -1
|
|
||||||
|
|
||||||
for y in range(self.height):
|
|
||||||
for x in range(self.width):
|
|
||||||
c = self.page.data[x][y]
|
|
||||||
|
|
||||||
if self.redraw or self.screen[x][y] != c:
|
|
||||||
if cursorX != x or cursorY != y:
|
|
||||||
self.lcd.goto(x, y)
|
|
||||||
cursorX, cursorY = x, y
|
|
||||||
|
|
||||||
self.lcd.put_char(c)
|
|
||||||
cursorX += 1
|
|
||||||
self.screen[x][y] = c
|
|
||||||
|
|
||||||
self.redraw = False
|
|
||||||
|
|
||||||
except IOError as e:
|
|
||||||
# Try next address
|
|
||||||
#self.addr_num += 1
|
|
||||||
#if len(self.addrs) <= self.addr_num: self.addr_num = 0
|
|
||||||
#self.addr = self.addrs[self.addr_num]
|
|
||||||
#self.lcd = None
|
|
||||||
|
|
||||||
#self.log.warning('LCD communication failed, ' +
|
|
||||||
# 'retrying on address 0x%02x: %s' % (self.addr, e))
|
|
||||||
|
|
||||||
#self.log.warning('LCD not present.')
|
|
||||||
|
|
||||||
#self.reset = True
|
|
||||||
self.reset = False
|
|
||||||
#self.timeout = self.ctrl.ioloop.call_later(1, self._update)
|
|
||||||
|
|
||||||
|
|
||||||
def goodbye(self, message = ''):
|
|
||||||
if self.timeout:
|
|
||||||
self.ctrl.ioloop.remove_timeout(self.timeout)
|
|
||||||
self.timeout = None
|
|
||||||
|
|
||||||
if self.redraw_timer:
|
|
||||||
self.ctrl.ioloop.remove_timeout(self.redraw_timer)
|
|
||||||
self.redraw_timer = None
|
|
||||||
|
|
||||||
if self.lcd is not None: self.set_message(message)
|
|
||||||
@@ -1,76 +0,0 @@
|
|||||||
################################################################################
|
|
||||||
# #
|
|
||||||
# This file is part of the Buildbotics firmware. #
|
|
||||||
# #
|
|
||||||
# Copyright (c) 2015 - 2018, Buildbotics LLC #
|
|
||||||
# All rights reserved. #
|
|
||||||
# #
|
|
||||||
# This file ("the software") is free software: you can redistribute it #
|
|
||||||
# and/or modify it under the terms of the GNU General Public License, #
|
|
||||||
# version 2 as published by the Free Software Foundation. You should #
|
|
||||||
# have received a copy of the GNU General Public License, version 2 #
|
|
||||||
# along with the software. If not, see <http://www.gnu.org/licenses/>. #
|
|
||||||
# #
|
|
||||||
# The software 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 #
|
|
||||||
# Lesser General Public License for more details. #
|
|
||||||
# #
|
|
||||||
# You should have received a copy of the GNU Lesser General Public #
|
|
||||||
# License along with the software. If not, see #
|
|
||||||
# <http://www.gnu.org/licenses/>. #
|
|
||||||
# #
|
|
||||||
# For information regarding this software email: #
|
|
||||||
# "Joseph Coffland" <joseph@buildbotics.com> #
|
|
||||||
# #
|
|
||||||
################################################################################
|
|
||||||
|
|
||||||
import bbctrl
|
|
||||||
|
|
||||||
|
|
||||||
class MainLCDPage(bbctrl.LCDPage):
|
|
||||||
def __init__(self, ctrl):
|
|
||||||
bbctrl.LCDPage.__init__(self, ctrl.lcd)
|
|
||||||
|
|
||||||
self.ctrl = ctrl
|
|
||||||
self.install = True
|
|
||||||
|
|
||||||
ctrl.state.add_listener(self.update)
|
|
||||||
|
|
||||||
|
|
||||||
def update(self, update):
|
|
||||||
state = self.ctrl.state
|
|
||||||
|
|
||||||
# Must be after machine vars have loaded
|
|
||||||
if self.install and hasattr(self, 'id'):
|
|
||||||
self.install = False
|
|
||||||
self.ctrl.lcd.set_current_page(self.id)
|
|
||||||
|
|
||||||
self.text('%-9s' % state.get('xx', ''), 0, 0)
|
|
||||||
|
|
||||||
metric = not state.get('imperial', False)
|
|
||||||
scale = 1 if metric else 25.4
|
|
||||||
|
|
||||||
# Show enabled axes
|
|
||||||
row = 0
|
|
||||||
for axis in 'xyzabc':
|
|
||||||
if state.is_axis_faulted(axis):
|
|
||||||
self.text(' FAULT %s' % axis.upper(), 9, row)
|
|
||||||
row += 1
|
|
||||||
|
|
||||||
elif state.is_axis_enabled(axis):
|
|
||||||
position = state.get(axis + 'p', 0)
|
|
||||||
position += state.get('offset_' + axis, 0)
|
|
||||||
position /= scale
|
|
||||||
self.text('% 10.3f%s' % (position, axis.upper()), 9, row)
|
|
||||||
row += 1
|
|
||||||
|
|
||||||
while row < 4:
|
|
||||||
self.text(' ' * 11, 9, row)
|
|
||||||
row += 1
|
|
||||||
|
|
||||||
# Show tool, units, feed and speed
|
|
||||||
self.text('%2uT' % state.get('tool', 0), 6, 1)
|
|
||||||
self.text('%-6s' % 'MM' if metric else 'INCH', 0, 1)
|
|
||||||
self.text('%8uF' % (state.get('feed', 0) / scale), 0, 2)
|
|
||||||
self.text('%8dS' % state.get('speed', 0), 0, 3)
|
|
||||||
@@ -68,7 +68,6 @@ class Pwr():
|
|||||||
|
|
||||||
self.i2c_addr = ctrl.args.pwr_addr
|
self.i2c_addr = ctrl.args.pwr_addr
|
||||||
self.regs = [-1] * 9
|
self.regs = [-1] * 9
|
||||||
self.lcd_page = ctrl.lcd.add_new_page()
|
|
||||||
self.failures = 0
|
self.failures = 0
|
||||||
|
|
||||||
self._update_cb(False)
|
self._update_cb(False)
|
||||||
@@ -179,16 +178,6 @@ class Pwr():
|
|||||||
self.failures = 0
|
self.failures = 0
|
||||||
return
|
return
|
||||||
|
|
||||||
self.lcd_page.text('%3dC Tmp' % self.regs[TEMP_REG], 0, 0)
|
|
||||||
self.lcd_page.text('%5.1fV In' % self.regs[VIN_REG], 0, 1)
|
|
||||||
self.lcd_page.text('%5.1fV Out' % self.regs[VOUT_REG], 0, 2)
|
|
||||||
self.lcd_page.text(' %04x Flg' % self.regs[FLAGS_REG], 0, 3)
|
|
||||||
|
|
||||||
self.lcd_page.text('%5.1fA Mot' % self.regs[MOTOR_REG], 10, 0)
|
|
||||||
self.lcd_page.text('%5.1fA Ld1' % self.regs[LOAD1_REG], 10, 1)
|
|
||||||
self.lcd_page.text('%5.1fA Ld2' % self.regs[LOAD2_REG], 10, 2)
|
|
||||||
self.lcd_page.text('%5.1fA Vdd' % self.regs[VDD_REG], 10, 3)
|
|
||||||
|
|
||||||
if len(update): self.ctrl.state.update(update)
|
if len(update): self.ctrl.state.update(update)
|
||||||
|
|
||||||
self.failures = 0
|
self.failures = 0
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ def call_get_output(cmd):
|
|||||||
|
|
||||||
class RebootHandler(bbctrl.APIHandler):
|
class RebootHandler(bbctrl.APIHandler):
|
||||||
def put_ok(self):
|
def put_ok(self):
|
||||||
self.get_ctrl().lcd.goodbye('Rebooting...')
|
|
||||||
subprocess.Popen('reboot')
|
subprocess.Popen('reboot')
|
||||||
|
|
||||||
|
|
||||||
@@ -193,13 +192,11 @@ class FirmwareUpdateHandler(bbctrl.APIHandler):
|
|||||||
with open('firmware/update.tar.bz2', 'wb') as f:
|
with open('firmware/update.tar.bz2', 'wb') as f:
|
||||||
f.write(firmware['body'])
|
f.write(firmware['body'])
|
||||||
|
|
||||||
self.get_ctrl().lcd.goodbye('Upgrading firmware')
|
|
||||||
subprocess.Popen(['/usr/local/bin/update-bbctrl'])
|
subprocess.Popen(['/usr/local/bin/update-bbctrl'])
|
||||||
|
|
||||||
|
|
||||||
class UpgradeHandler(bbctrl.APIHandler):
|
class UpgradeHandler(bbctrl.APIHandler):
|
||||||
def put_ok(self):
|
def put_ok(self):
|
||||||
self.get_ctrl().lcd.goodbye('Upgrading firmware')
|
|
||||||
subprocess.Popen(['/usr/local/bin/upgrade-bbctrl'])
|
subprocess.Popen(['/usr/local/bin/upgrade-bbctrl'])
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -40,7 +40,6 @@ from bbctrl.RequestHandler import RequestHandler
|
|||||||
from bbctrl.APIHandler import APIHandler
|
from bbctrl.APIHandler import APIHandler
|
||||||
from bbctrl.FileHandler import FileHandler
|
from bbctrl.FileHandler import FileHandler
|
||||||
from bbctrl.Config import Config
|
from bbctrl.Config import Config
|
||||||
from bbctrl.LCD import LCD, LCDPage
|
|
||||||
from bbctrl.Mach import Mach
|
from bbctrl.Mach import Mach
|
||||||
from bbctrl.Web import Web
|
from bbctrl.Web import Web
|
||||||
from bbctrl.Jog import Jog
|
from bbctrl.Jog import Jog
|
||||||
@@ -52,8 +51,6 @@ from bbctrl.Preplanner import Preplanner
|
|||||||
from bbctrl.State import State
|
from bbctrl.State import State
|
||||||
from bbctrl.Comm import Comm
|
from bbctrl.Comm import Comm
|
||||||
from bbctrl.CommandQueue import CommandQueue
|
from bbctrl.CommandQueue import CommandQueue
|
||||||
from bbctrl.MainLCDPage import MainLCDPage
|
|
||||||
from bbctrl.IPLCDPage import IPLCDPage
|
|
||||||
from bbctrl.Camera import Camera, VideoHandler
|
from bbctrl.Camera import Camera, VideoHandler
|
||||||
from bbctrl.AVR import AVR
|
from bbctrl.AVR import AVR
|
||||||
from bbctrl.AVREmu import AVREmu
|
from bbctrl.AVREmu import AVREmu
|
||||||
@@ -132,8 +129,6 @@ def parse_args():
|
|||||||
help = 'Serial baud rate')
|
help = 'Serial baud rate')
|
||||||
parser.add_argument('--i2c-port', default = 1, type = int,
|
parser.add_argument('--i2c-port', default = 1, type = int,
|
||||||
help = 'I2C port')
|
help = 'I2C port')
|
||||||
parser.add_argument('--lcd-addr', default = [0x27, 0x3f], type = int,
|
|
||||||
help = 'LCD I2C address')
|
|
||||||
parser.add_argument('--avr-addr', default = 0x2b, type = int,
|
parser.add_argument('--avr-addr', default = 0x2b, type = int,
|
||||||
help = 'AVR I2C address')
|
help = 'AVR I2C address')
|
||||||
parser.add_argument('--pwr-addr', default = 0x60, type = int,
|
parser.add_argument('--pwr-addr', default = 0x60, type = int,
|
||||||
|
|||||||
@@ -72,12 +72,6 @@ class JogHandler:
|
|||||||
log.info(axes_to_string(self.axes) + ' x {:d}'.format(self.speed))
|
log.info(axes_to_string(self.axes) + ' x {:d}'.format(self.speed))
|
||||||
|
|
||||||
|
|
||||||
def up(self): log.debug('up')
|
|
||||||
def down(self): log.debug('down')
|
|
||||||
def left(self): log.debug('left')
|
|
||||||
def right(self): log.debug('right')
|
|
||||||
|
|
||||||
|
|
||||||
def reset(self):
|
def reset(self):
|
||||||
self.axes = [0.0, 0.0, 0.0, 0.0]
|
self.axes = [0.0, 0.0, 0.0, 0.0]
|
||||||
self.speed = 3
|
self.speed = 3
|
||||||
@@ -105,17 +99,6 @@ class JogHandler:
|
|||||||
if event.type == EV_ABS and event.code in config['axes']:
|
if event.type == EV_ABS and event.code in config['axes']:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
elif event.type == EV_ABS and event.code in config['arrows']:
|
|
||||||
axis = config['arrows'].index(event.code)
|
|
||||||
|
|
||||||
if event.value < 0:
|
|
||||||
if axis == 1: self.up()
|
|
||||||
else: self.left()
|
|
||||||
|
|
||||||
elif 0 < event.value:
|
|
||||||
if axis == 1: self.down()
|
|
||||||
else: self.right()
|
|
||||||
|
|
||||||
elif event.type == EV_KEY and event.code in config['speed']:
|
elif event.type == EV_KEY and event.code in config['speed']:
|
||||||
old_speed = self.speed
|
old_speed = self.speed
|
||||||
self.speed = config['speed'].index(event.code) + 1
|
self.speed = config['speed'].index(event.code) + 1
|
||||||
|
|||||||
@@ -1,236 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
################################################################################
|
|
||||||
# #
|
|
||||||
# This file is part of the Buildbotics firmware. #
|
|
||||||
# #
|
|
||||||
# Copyright (c) 2015 - 2018, Buildbotics LLC #
|
|
||||||
# All rights reserved. #
|
|
||||||
# #
|
|
||||||
# This file ("the software") is free software: you can redistribute it #
|
|
||||||
# and/or modify it under the terms of the GNU General Public License, #
|
|
||||||
# version 2 as published by the Free Software Foundation. You should #
|
|
||||||
# have received a copy of the GNU General Public License, version 2 #
|
|
||||||
# along with the software. If not, see <http://www.gnu.org/licenses/>. #
|
|
||||||
# #
|
|
||||||
# The software 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 #
|
|
||||||
# Lesser General Public License for more details. #
|
|
||||||
# #
|
|
||||||
# You should have received a copy of the GNU Lesser General Public #
|
|
||||||
# License along with the software. If not, see #
|
|
||||||
# <http://www.gnu.org/licenses/>. #
|
|
||||||
# #
|
|
||||||
# For information regarding this software email: #
|
|
||||||
# "Joseph Coffland" <joseph@buildbotics.com> #
|
|
||||||
# #
|
|
||||||
################################################################################
|
|
||||||
|
|
||||||
import time
|
|
||||||
import logging
|
|
||||||
|
|
||||||
|
|
||||||
log = logging.getLogger('LCD')
|
|
||||||
|
|
||||||
|
|
||||||
# Control flags
|
|
||||||
REG_SELECT_BIT = 1 << 0
|
|
||||||
READ_BIT = 1 << 1
|
|
||||||
ENABLE_BIT = 1 << 2
|
|
||||||
BACKLIGHT_BIT = 1 << 3
|
|
||||||
|
|
||||||
# Commands
|
|
||||||
LCD_CLEAR_DISPLAY = 1 << 0
|
|
||||||
LCD_RETURN_HOME = 1 << 1
|
|
||||||
LCD_ENTRY_MODE_SET = 1 << 2
|
|
||||||
LCD_DISPLAY_CONTROL = 1 << 3
|
|
||||||
LCD_CURSOR_SHIFT = 1 << 4
|
|
||||||
LCD_FUNCTION_SET = 1 << 5
|
|
||||||
LCD_SET_CGRAM_ADDR = 1 << 6
|
|
||||||
LCD_SET_DDRAM_ADDR = 1 << 7
|
|
||||||
|
|
||||||
# Entry Mode Set flags
|
|
||||||
LCD_ENTRY_SHIFT_DISPLAY = 1 << 0
|
|
||||||
LCD_ENTRY_SHIFT_INC = 1 << 1
|
|
||||||
LCD_ENTRY_SHIFT_DEC = 0 << 1
|
|
||||||
|
|
||||||
# Display Control flags
|
|
||||||
LCD_BLINK_ON = 1 << 0
|
|
||||||
LCD_BLINK_OFF = 0 << 0
|
|
||||||
LCD_CURSOR_ON = 1 << 1
|
|
||||||
LCD_CURSOR_OFF = 0 << 1
|
|
||||||
LCD_DISPLAY_ON = 1 << 2
|
|
||||||
LCD_DISPLAY_OFF = 0 << 2
|
|
||||||
|
|
||||||
# Cursor Shift flags
|
|
||||||
LCD_SHIFT_RIGHT = 1 << 2
|
|
||||||
LCD_SHIFT_LEFT = 0 << 2
|
|
||||||
LCD_SHIFT_DISPLAY = 1 << 3
|
|
||||||
LCD_SHIFT_CURSOR = 0 << 3
|
|
||||||
|
|
||||||
# Function Set flags
|
|
||||||
LCD_5x11_DOTS = 1 << 2
|
|
||||||
LCD_5x8_DOTS = 0 << 2
|
|
||||||
LCD_2_LINE = 1 << 3
|
|
||||||
LCD_1_LINE = 0 << 3
|
|
||||||
LCD_8_BIT_MODE = 1 << 4
|
|
||||||
LCD_4_BIT_MODE = 0 << 4
|
|
||||||
|
|
||||||
# Text justification flags
|
|
||||||
JUSTIFY_LEFT = 0
|
|
||||||
JUSTIFY_RIGHT = 1
|
|
||||||
JUSTIFY_CENTER = 2
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class LCD:
|
|
||||||
def __init__(self, i2c, addr, height = 4, width = 20):
|
|
||||||
self.addr = addr
|
|
||||||
self.height = height
|
|
||||||
self.width = width
|
|
||||||
self.i2c = i2c
|
|
||||||
self.backlight = True
|
|
||||||
|
|
||||||
self.reset()
|
|
||||||
|
|
||||||
|
|
||||||
def reset(self):
|
|
||||||
self.clear()
|
|
||||||
time.sleep(0.050)
|
|
||||||
self.write_nibble(3 << 4) # Home
|
|
||||||
time.sleep(0.050)
|
|
||||||
self.write_nibble(3 << 4) # Home
|
|
||||||
time.sleep(0.050)
|
|
||||||
self.write_nibble(3 << 4) # Home
|
|
||||||
self.write_nibble(2 << 4) # 4-bit
|
|
||||||
|
|
||||||
self.write(LCD_FUNCTION_SET | LCD_2_LINE | LCD_5x8_DOTS |
|
|
||||||
LCD_4_BIT_MODE)
|
|
||||||
self.write(LCD_DISPLAY_CONTROL | LCD_DISPLAY_ON)
|
|
||||||
self.write(LCD_ENTRY_MODE_SET | LCD_ENTRY_SHIFT_INC)
|
|
||||||
|
|
||||||
|
|
||||||
def write_i2c(self, data):
|
|
||||||
if self.backlight: data |= BACKLIGHT_BIT
|
|
||||||
|
|
||||||
self.i2c.write(self.addr, data)
|
|
||||||
time.sleep(0.0001)
|
|
||||||
|
|
||||||
|
|
||||||
# Write half of a command to LCD
|
|
||||||
def write_nibble(self, data):
|
|
||||||
self.write_i2c(data)
|
|
||||||
|
|
||||||
# Strobe
|
|
||||||
self.write_i2c(data | ENABLE_BIT)
|
|
||||||
time.sleep(0.0005)
|
|
||||||
|
|
||||||
self.write_i2c(data & ~ENABLE_BIT)
|
|
||||||
time.sleep(0.0001)
|
|
||||||
|
|
||||||
|
|
||||||
# Write an 8-bit command to LCD
|
|
||||||
def write(self, cmd, flags = 0):
|
|
||||||
self.write_nibble(flags | (cmd & 0xf0))
|
|
||||||
self.write_nibble(flags | ((cmd << 4) & 0xf0))
|
|
||||||
|
|
||||||
|
|
||||||
def set_cursor(self, on, blink):
|
|
||||||
data = LCD_DISPLAY_CONTROL
|
|
||||||
|
|
||||||
if on: data |= LCD_CURSOR_ON
|
|
||||||
if blink: data |= LCD_BLINK_ON
|
|
||||||
|
|
||||||
self.write(data)
|
|
||||||
|
|
||||||
|
|
||||||
def set_backlight(self, enable):
|
|
||||||
self.backlight = enable
|
|
||||||
self.write_i2c(0)
|
|
||||||
|
|
||||||
|
|
||||||
def program_char(self, addr, data):
|
|
||||||
if addr < 0 or 8 <= addr: return
|
|
||||||
|
|
||||||
self.write(LCD_SET_CGRAM_ADDR | (addr << 3))
|
|
||||||
for x in data:
|
|
||||||
self.write(x, REG_SELECT_BIT)
|
|
||||||
|
|
||||||
|
|
||||||
def goto(self, x, y):
|
|
||||||
if x < 0 or self.width <= x or y < 0 or self.height <= y: return
|
|
||||||
self.write(LCD_SET_DDRAM_ADDR | (0, 64, 20, 84)[y] + int(x))
|
|
||||||
|
|
||||||
|
|
||||||
def put_char(self, c):
|
|
||||||
self.write(ord(c), REG_SELECT_BIT)
|
|
||||||
|
|
||||||
|
|
||||||
def text(self, msg, x = None, y = None):
|
|
||||||
if x is not None and y is not None: self.goto(x, y)
|
|
||||||
|
|
||||||
for c in msg: self.put_char(c)
|
|
||||||
|
|
||||||
|
|
||||||
def display(self, line, msg, justify = JUSTIFY_LEFT):
|
|
||||||
if justify == JUSTIFY_RIGHT: x = self.width - len(msg)
|
|
||||||
elif justify == JUSTIFY_CENTER: x = (self.width - len(msg)) / 2
|
|
||||||
else: x = 0
|
|
||||||
|
|
||||||
if x < 0: x = 0
|
|
||||||
|
|
||||||
self.text(msg, x, line)
|
|
||||||
|
|
||||||
|
|
||||||
def shift(self, count = 1, right = True, display = True):
|
|
||||||
cmd = LCD_CURSOR_SHIFT
|
|
||||||
if right: cmd |= LCD_SHIFT_RIGHT
|
|
||||||
if display: cmd |= LCD_SHIFT_DISPLAY
|
|
||||||
|
|
||||||
for i in range(count): self.write(cmd)
|
|
||||||
|
|
||||||
|
|
||||||
# Clear LCD and move cursor home
|
|
||||||
def clear(self):
|
|
||||||
self.write(LCD_CLEAR_DISPLAY)
|
|
||||||
self.write(LCD_RETURN_HOME)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
lcd = LCD(1, 0x27)
|
|
||||||
|
|
||||||
lcd.clear()
|
|
||||||
|
|
||||||
lcd.program_char(0, (0b11011,
|
|
||||||
0b11011,
|
|
||||||
0b00000,
|
|
||||||
0b01100,
|
|
||||||
0b01100,
|
|
||||||
0b00000,
|
|
||||||
0b11011,
|
|
||||||
0b11011))
|
|
||||||
|
|
||||||
lcd.program_char(1, (0b11000,
|
|
||||||
0b01100,
|
|
||||||
0b00110,
|
|
||||||
0b00011,
|
|
||||||
0b00011,
|
|
||||||
0b00110,
|
|
||||||
0b01100,
|
|
||||||
0b11000))
|
|
||||||
|
|
||||||
lcd.program_char(2, (0b00011,
|
|
||||||
0b00110,
|
|
||||||
0b01100,
|
|
||||||
0b11000,
|
|
||||||
0b11000,
|
|
||||||
0b01100,
|
|
||||||
0b00110,
|
|
||||||
0b00011))
|
|
||||||
|
|
||||||
lcd.display(0, '\0' * lcd.width)
|
|
||||||
lcd.display(1, 'Hello world!', JUSTIFY_CENTER)
|
|
||||||
lcd.display(2, '\1\2' * (lcd.width / 2))
|
|
||||||
lcd.display(3, '12345678901234567890')
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
################################################################################
|
|
||||||
# #
|
|
||||||
# This file is part of the Buildbotics firmware. #
|
|
||||||
# #
|
|
||||||
# Copyright (c) 2015 - 2018, Buildbotics LLC #
|
|
||||||
# All rights reserved. #
|
|
||||||
# #
|
|
||||||
# This file ("the software") is free software: you can redistribute it #
|
|
||||||
# and/or modify it under the terms of the GNU General Public License, #
|
|
||||||
# version 2 as published by the Free Software Foundation. You should #
|
|
||||||
# have received a copy of the GNU General Public License, version 2 #
|
|
||||||
# along with the software. If not, see <http://www.gnu.org/licenses/>. #
|
|
||||||
# #
|
|
||||||
# The software 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 #
|
|
||||||
# Lesser General Public License for more details. #
|
|
||||||
# #
|
|
||||||
# You should have received a copy of the GNU Lesser General Public #
|
|
||||||
# License along with the software. If not, see #
|
|
||||||
# <http://www.gnu.org/licenses/>. #
|
|
||||||
# #
|
|
||||||
# For information regarding this software email: #
|
|
||||||
# "Joseph Coffland" <joseph@buildbotics.com> #
|
|
||||||
# #
|
|
||||||
################################################################################
|
|
||||||
|
|
||||||
import lcd
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
screen = lcd.LCD(1, 0x27)
|
|
||||||
|
|
||||||
screen.clear()
|
|
||||||
screen.display(0, 'Buildbotics', lcd.JUSTIFY_CENTER)
|
|
||||||
screen.display(1, 'Controller', lcd.JUSTIFY_CENTER)
|
|
||||||
screen.display(3, 'Booting...', lcd.JUSTIFY_CENTER)
|
|
||||||
Reference in New Issue
Block a user