Skip to content

Commit

Permalink
Merge pull request #16 from MausTec/vibrate-modes
Browse files Browse the repository at this point in the history
Vibrate modes
  • Loading branch information
MauAbata authored Jun 11, 2021
2 parents bbdc34c + 3760d93 commit 69721a4
Show file tree
Hide file tree
Showing 22 changed files with 648 additions and 139 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,6 @@ cmake-build-release/

build/

serials.yml
serials.yml
VERSION.h
.vscode/
41 changes: 12 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,29 +45,30 @@ and is automatically generated. Here is a quick summary of config variables:
|`update_frequency_hz`|Int|50|Update frequency for pressure readings and arousal steps. Higher = crash your serial monitor.|
|`sensor_sensitivity`|Byte|128|Analog pressure prescaling. Adjust this until the pressure is ~60-70%|
|`use_average_values`|Boolean|false|Use average values when calculating arousal. This smooths noisy data.|
|`vibration_mode`|VibrationMode|RampStop|Vibration Mode for main vibrator control.|

\* AzureFang refers to a common wireless technology that is blue and involves chewing face-rocks. However, the
trademark holders of this technology require the name to be licensed, so we're totally just using AzureFang.

### Vibration Modes:

|ID|Name|Description|
|---|---|---|
|1|Ramp-Stop|Vibrator ramps up from set min speed to max speed, stopping abruptly on arousal threshold crossing.|
|2|Depletion|Vibrator speed ramps up from min to max, but is reduced as arousal approaches threshold.|
|3|Enhancement|Vibrator speed ramps up as arousal increases, holding a peak for ramp_time.|
|0|Global Sync|When set on secondary vibrators, they will follow the primary vibrator speed.|

## Hardware

Hardware builds for this project can be purchased from Maus-Tec Electronics, at [maustec.io/nogasm](https://maustec.io/nogasm).
OSHD pending final review.
Hardware builds for this project can be purchased from Maus-Tec Electronics, at [maustec.io/nogasm](https://maustec.io/eom).

Hardware development and assembly helps keep pizza in the freezer and a roof over the head of the maintainer.
Your support helps a small business grow into something neat, and ensures future devices like this can continue
to be produced.

The User Guide for the hardware can be downloaded at [doc/Edge-o-Matic_UserGuide.docx](doc/Edge-o-Matic_UserGuide.docx).

### ESP32 Pinout

If you want to breadboard this project, I've included the pinout from the ESP32 below. Please reference the original
NoGasm schematic for specific designs regarding the pressure prescaler and MOSFET wiring. Alternatively, ask Mau about
their breadboard-friendly MOSFET boards, which can directly drive your power rails and your motor from 12V.

Full pinout details are in the Operator's Manual.

### That RJ45 Jack

**The RJ45 Jack IS NOT ETHERNET!** That is a balanced twisted pair extension of the I2C bus on the controller, and is available
Expand Down Expand Up @@ -103,6 +104,7 @@ This project uses the following libraries:
- Adafruit SSD1306 library by Adafruit (click "Install All" if it prompts you for dependencies)
- ESP32Servo library by Kevin Harrington
- ESP32 I2C Slave library by Gutierrez PS
- NimBLE (v1.2): https://github.com/h2zero/NimBLE-Arduino

#### Board Settings

Expand All @@ -118,25 +120,6 @@ This project uses the following libraries:
|Core Debug Level|None|
|PSRAM|Disabled|

# Thanks!

For helping develop the software, hardware, and other nerdy bits:

- @Rhoboto
- @qDot

For being the first to order the NoGasm WiFi during the 5 unit pre-order run:

- @hardplayswitch
- (anonymous)
-
-
-

For supporting my initial endeavour in hardware assembly and helping me scale:

- @homphs

# Contributions

Any changes to configuration values should be linted. Run `ruby bin/config_lint.rb` to check documentation, serializers
Expand Down
1 change: 0 additions & 1 deletion VERSION.h

This file was deleted.

19 changes: 14 additions & 5 deletions bin/config_lint.rb
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ def error(file, line, message)
end

# Check Read
if line =~ /Config\.(\w+)\s*=\s*doc\["(\w+)"\](\s*\|\s*\S+)?/
if line =~ /Config\.(\w+)\s*=(?:\s*\(\w+\))?\s*doc\["(\w+)"\](\s*\|\s*\S+)?/
json_reads << $2
type = config_values[$1]
if $1 != $2
Expand All @@ -84,7 +84,9 @@ def error(file, line, message)
if $3.nil? || $3 == ""
error config_cpp, i, "JSON read #{$2.inspect} missing default value for #{type.inspect}"
else
json_defaults[$1] = $3.gsub(/\s*\|\s*/, '').gsub(/;\s*$/, '')
key = $1
default_set = $3.gsub(/\s*\|\s*/, '').gsub(/;\s*$/, '')
json_defaults[key] = default_set.gsub(/#{type}::/, '')
end
if type =~ /String|char\[\d+\]/
error config_cpp, i, "JSON assigns #{$2.inspect} to string type! Use strlcpy!"
Expand Down Expand Up @@ -115,7 +117,7 @@ def error(file, line, message)
end

# Check Assignment
if line =~ /doc\s*\[\"(\w+)\"\]\s*=\s*Config\.(\w+)/
if line =~ /doc\s*\[\"(\w+)\"\]\s*=(?:\s*\(\w+\))?\s*Config\.(\w+)/
type = config_values[$2]
json_assignments << $1
if $1 != $2
Expand Down Expand Up @@ -166,7 +168,7 @@ def error(file, line, message)
markers[$1] = $i
end

if line =~ /String\s*\(\s*Config\.(\w+)/
if line =~ /String\s*\((?:\s*\(\w+\))?\s*Config\.(\w+)/
console_gets << $1
type = config_values[$1]
if ($1 != last_check)
Expand Down Expand Up @@ -197,8 +199,13 @@ def error(file, line, message)
if setter !~ /atoi\s*\(/
error console_cpp, i, "Config option #{option.inspect} is #{type}, use atoi()"
end
when /^([A-Z][a-zA-Z]+)$/
# Assume Enums Here
if setter !~ /\(#{$1}\)\s+atoi\s*\(/
error console_cpp, i, "Config option #{option.inspect} needs cast to #{type}, got: #{setter}"
end
else
error console_cpp, i, "Config option #{option.inspect} using invalid setter"
error console_cpp, i, "Config option #{option.inspect} using invalid setter: #{setter}"
end
end

Expand Down Expand Up @@ -266,6 +273,8 @@ def error(file, line, message)
"String"
when "bool"
"Boolean"
when /^[A-Z]/
valid_type
else
valid_type.capitalize
end
Expand Down
16 changes: 8 additions & 8 deletions bin/lib/arduino.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@
#-build-path C:\Users\eiser.000\AppData\Local\Temp\arduino_build_233518
#-warnings=none
#-prefs=build.warn_data_percentage=75
#-prefs=runtime.tools.esptool_py.path=C:\Users\eiser.000\AppData\Local\Arduino15\packages\esp32\tools\esptool_py\2.6.1
#-prefs=runtime.tools.esptool_py-2.6.1.path=C:\Users\eiser.000\AppData\Local\Arduino15\packages\esp32\tools\esptool_py\2.6.1
#-prefs=runtime.tools.esptool_py.path=C:\Users\eiser.000\AppData\Local\Arduino15\packages\esp32\tools\esptool_py\3.0.0
#-prefs=runtime.tools.esptool_py-3.0.0.path=C:\Users\eiser.000\AppData\Local\Arduino15\packages\esp32\tools\esptool_py\3.0.0
#-prefs=runtime.tools.mkspiffs.path=C:\Users\eiser.000\AppData\Local\Arduino15\packages\esp32\tools\mkspiffs\0.2.3
#-prefs=runtime.tools.mkspiffs-0.2.3.path=C:\Users\eiser.000\AppData\Local\Arduino15\packages\esp32\tools\mkspiffs\0.2.3
#-prefs=runtime.tools.xtensa-esp32-elf-gcc.path=C:\Users\eiser.000\AppData\Local\Arduino15\packages\esp32\tools\xtensa-esp32-elf-gcc\1.22.0-80-g6c4433a-5.2.0
#-prefs=runtime.tools.xtensa-esp32-elf-gcc-1.22.0-80-g6c4433a-5.2.0.path=C:\Users\eiser.000\AppData\Local\Arduino15\packages\esp32\tools\xtensa-esp32-elf-gcc\1.22.0-80-g6c4433a-5.2.0
#-prefs=runtime.tools.xtensa-esp32-elf-gcc.path=C:\Users\eiser.000\AppData\Local\Arduino15\packages\esp32\tools\xtensa-esp32-elf-gcc\1.22.0-97-gc752ad5-5.2.0
#-prefs=runtime.tools.xtensa-esp32-elf-gcc-1.22.0-97-gc752ad5-5.2.0.path=C:\Users\eiser.000\AppData\Local\Arduino15\packages\esp32\tools\xtensa-esp32-elf-gcc\1.22.0-97-gc752ad5-5.2.0
#-verbose
#E:\Documents\Arduino\ESP32_WiFi\nogasm-wifi.ino

Expand Down Expand Up @@ -50,12 +50,12 @@ def initialize(ino_file, builder_opts={}, esp_opts={})
@prefs = {
'HTTPS_DISABLE_SELFSIGNING' => 'true',
'build.warn_data_percentage' => '75',
'runtime.tools.esptool_py.path' => 'C:\Users\eiser.000\AppData\Local\Arduino15\packages\esp32\tools\esptool_py\2.6.1',
'runtime.tools.esptool_py-2.6.1.path' => 'C:\Users\eiser.000\AppData\Local\Arduino15\packages\esp32\tools\esptool_py\2.6.1',
'runtime.tools.esptool_py.path' => 'C:\Users\eiser.000\AppData\Local\Arduino15\packages\esp32\tools\esptool_py\3.0.0',
'runtime.tools.esptool_py-3.0.0.path' => 'C:\Users\eiser.000\AppData\Local\Arduino15\packages\esp32\tools\esptool_py\3.0.0',
'runtime.tools.mkspiffs.path' => 'C:\Users\eiser.000\AppData\Local\Arduino15\packages\esp32\tools\mkspiffs\0.2.3',
'runtime.tools.mkspiffs-0.2.3.path' => 'C:\Users\eiser.000\AppData\Local\Arduino15\packages\esp32\tools\mkspiffs\0.2.3',
'runtime.tools.xtensa-esp32-elf-gcc.path' => 'C:\Users\eiser.000\AppData\Local\Arduino15\packages\esp32\tools\xtensa-esp32-elf-gcc\1.22.0-80-g6c4433a-5.2.0',
'runtime.tools.xtensa-esp32-elf-gcc-1.22.0-80-g6c4433a-5.2.0.path' => 'C:\Users\eiser.000\AppData\Local\Arduino15\packages\esp32\tools\xtensa-esp32-elf-gcc\1.22.0-80-g6c4433a-5.2.0'
'runtime.tools.xtensa-esp32-elf-gcc.path' => 'C:\Users\eiser.000\AppData\Local\Arduino15\packages\esp32\tools\xtensa-esp32-elf-gcc\1.22.0-97-gc752ad5-5.2.0',
'runtime.tools.xtensa-esp32-elf-gcc-1.22.0-97-gc752ad5-5.2.0.path' => 'C:\Users\eiser.000\AppData\Local\Arduino15\packages\esp32\tools\xtensa-esp32-elf-gcc\1.22.0-97-gc752ad5-5.2.0'
}

@tools = [
Expand Down
56 changes: 52 additions & 4 deletions bin/lib/esptool.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@

class ESPTool
ROOT_PATH = File.absolute_path(File.join(File.dirname(__FILE__), "..", "..")).freeze
ESPTOOL_PATH = 'C:\Users\eiser.000\AppData\Local\Arduino15\packages\esp32\tools\esptool_py\2.6.1'.freeze
HARDWARE_PATH = 'C:\Users\eiser.000\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.4'.freeze
ESPTOOL_PATH = 'C:\Users\eiser.000\AppData\Local\Arduino15\packages\esp32\tools\esptool_py\3.0.0'.freeze
HARDWARE_PATH = 'C:\Users\eiser.000\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.6'.freeze
ESPTOOL_BIN = File.join(ESPTOOL_PATH, "esptool.exe").freeze

def initialize(port, bin_dir=ESPTOOL_PATH, bin_options={})
Expand Down Expand Up @@ -87,14 +87,31 @@ def set_serial(serial_no)
def console!
serial = Serial.new(@port, @baud)
read_thr = Thread.new do
in_stack_trace = false
stack_trace = []
loop do
begin
line = serial.gets

if line =~ /[A-Za-z0-9]{120,}/
save_screenshot(line.chomp)
else
puts line
end

if line =~ /abort\(\) was called|Guru Meditation Error/
stack_trace = []
in_stack_trace = true
end

if in_stack_trace
stack_trace.push line
end

if line =~ /Backtrace:/
in_stack_trace = false
puts decode_exception(stack_trace.join("\n"))
end
rescue RubySerial::Error => e
if Thread.current.report_on_exception
read_thr.report_on_exception = false
Expand Down Expand Up @@ -139,7 +156,7 @@ def build_opts_array(options={})

def search_ports_win
ports = {}
1.upto 64 do |index|
1.upto 255 do |index|
begin
serial = Serial.new portname = 'COM' + index.to_s
ports[portname] = 'is available' if serial
Expand All @@ -157,7 +174,7 @@ def select_port(default_port)

if port == 'auto'
found_ports = search_ports_win
ignored_ports = ['COM1', 'COM18']
ignored_ports = ['COM1', 'COM5']

# Reject COM1, maybe you don't want this
if found_ports.length > 1
Expand All @@ -179,6 +196,37 @@ def select_port(default_port)
port
end

def decode_exception(dump=nil)
cd = File.join(File.dirname(__FILE__), '..', '..')
jarfile = File.absolute_path(File.join(cd, 'tmp', 'esp-exception-decoder.jar'))
addr2line = "C:\\MinGW\\bin\\addr2line.exe"
exceptiontxt = File.absolute_path(File.join(cd, 'tmp', 'exception.txt'))
elffile = File.absolute_path(File.join(cd, 'build', 'arduino', 'nogasm-wifi.ino.elf'))

if dump
File.unlink(exceptiontxt)
File.write(exceptiontxt, dump)
end

args = [
'-jar',
jarfile,
addr2line,
elffile,
exceptiontxt
]

out = []
err = []

Open3::popen3("java", *args) do |sin, sout, serr, wait_thr|
sout.each_line { |l| out << l }
serr.each_line { |l| err << l }
end

[ out, err ]
end

def read_serial(serial, match = /^\r\n$/, timeout = 3)
line = nil
Timeout::timeout(5) do
Expand Down
28 changes: 26 additions & 2 deletions bin/upload.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,18 @@
opt :tag, "Tag this as a release and push", type: :bool, default: false
opt :serial, "Set a serial number for this device", type: :string, default: nil
opt :serial_prefix, "Autogen a serial from serials.yml", type: :string, default: nil
opt :serial_variant, "Append a veriant to the serial number.", type: :string, default: nil
opt :file_path, "Copy binary to a file path for update", type: :string, default: nil
opt :console, "Open a console to the device", type: :bool, default: false
opt :exception, "Decode the last exception dump", type: :bool, default: false
end

def get_version
$version ||= begin
(tag, n, sha) = `git describe --tags`.split('-')
v = Semantic::Version.new(tag.gsub(/^v/, ''))
if n.to_i > 0
v.build = sha
v.build = sha.chop
end
v
end
Expand All @@ -54,6 +56,19 @@ def sh(cmd)
puts `#{cmd}`
end

if opts[:exception]
tool = ESPTool.new nil
puts tool.send(:decode_exception, <<-DUMP)
/home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/queue.c:1442 (xQueueGenericReceive)- assert failed!
abort() was called at PC 0x4009002d on core 1
Backtrace: 0x400941ac:0x3ffd1700 0x400943dd:0x3ffd1720 0x4009002d:0x3ffd1740 0x400eb08e:0x3ffd1780 0x400f3bb2:0x3ffd17a0 0x400f3c31:0x3ffd17c0 0x400f3824:0x3ffd17e0 0x400f3961:0x3ffd1820 0x400ee8d2:0x3ffd1840 0x400eea64:0x3ffd1870 0x400e
ef16:0x3ffd1890 0x400e69db:0x3ffd18b0 0x400d38cd:0x3ffd18d0 0x400d38ea:0x3ffd18f0 0x400dfc82:0x3ffd1910 0x401d1c97:0x3ffd1930 0x400d7269:0x3ffd1950 0x400d737b:0x3ffd1980 0x400d9006:0x3ffd19b0 0x400d4f8a:0x3ffd19d0 0x400e4ddd:0x3ffd19f0 0
x400e4e8a:0x3ffd1a10 0x400d4fdb:0x3ffd1a30 0x400d3656:0x3ffd1a50 0x401070ed:0x3ffd1a70 0x40090341:0x3ffd1a90
DUMP
exit 0
end

if opts[:get_version]
puts get_version.to_s
exit
Expand All @@ -66,6 +81,9 @@ def sh(cmd)
elsif opts[:set_version]
v = Semantic::Version.new(opts[:set_version])
set_version(v)
else
v = get_version
set_version(v)
end

if opts[:compile]
Expand Down Expand Up @@ -108,7 +126,13 @@ def sh(cmd)
serials = YAML.load(File.read("serials.yml"));
last_ser = serials[prefix]
last_ser += 1
if esptool&.set_serial("%s-%02d%03d" % [prefix, Date.today.year % 100, last_ser])

serial = "%s-%02d%03d" % [prefix, Date.today.year % 100, last_ser]
if (variant = opts[:serial_variant])
serial += "-" + variant
end

if esptool&.set_serial(serial)
serials[prefix] = last_ser
File.write("serials.yml", YAML.dump(serials))
end
Expand Down
4 changes: 4 additions & 0 deletions config.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include "arduino.h"
#include "errors.h"
#include "include/VibrationModeController.h"

#include <ArduinoJson.h>

Expand Down Expand Up @@ -109,6 +110,9 @@ struct ConfigStruct {
int update_frequency_hz;
byte sensor_sensitivity;
bool use_average_values;

// Vibration Output Mode
VibrationMode vibration_mode;
} extern Config;

extern void loadConfigFromSd();
Expand Down
6 changes: 3 additions & 3 deletions include/BluetoothServer.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
#include <arduino.h>
#include "../config.h"

#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
#include <NimBLEDevice.h>
//#include <NimBLEUtils.h>
//#include <NimBLEServer.h>

#define SERVICE_UUID "52ecdfe9-590c-4226-8529-dd6bf4d817a6"
#define CHARACTERISTIC_UUID "9f13cb96-7739-4558-8bd7-53654909962d"
Expand Down
Loading

0 comments on commit 69721a4

Please sign in to comment.