Hackathon #1: Alvik Animal Dance

Students were put in small groups of about 3 and given 30 minutes to build a dancing animal with an Alvik. They could use any other materials and/or LEGO in the room. This resulting placemat is a student facing document that could be given to groups in the future to get them started with this activity.

Animal Dance Student Work

Hackathon #2: Alvik Swarms and a little BLE

Students were put into small groups of 3 and given an Alvik and a LEGO SPIKE Essentials hub. The goal was to get the Alvik talking to the Essential with BLE. They were also challenged to use the laser cutter to add pieces to the Alvik. Here is the link for the placemat that can be used for this activity. The BLE Library is at the bottom of this page.

BLE Student Work

Other Wacky Alvik builds

Students came up with lot of fun wacky builds. We have included a student facing placement that can be used to inspire these types of creations. Student work is included below.

Wacky Alvik builds - Student Work

Links for all of the Alvik placemats

Dancing Animals Placemat

dancing animal screen shot.png

Alvik Swarms BLE Placemat

Screenshot 2024-07-16 at 2.54.13 PM.png

Wacky Alvik Builds

Screenshot 2024-07-16 at 2.52.14 PM.png

BLE Library - Use this library for Alvik Swarms BLE projects

import bluetooth
import struct

NAME_FLAG = 0x09
IRQ_SCAN_RESULT = 5
IRQ_SCAN_DONE = 6

class Yell:
    def __init__(self):
        self._ble = bluetooth.BLE()
        self._ble.active(True)
        
    def advertise(self, name = 'Pico', interval_us=100000):
        short = name[:8]
        payload = struct.pack("BB", len(short) + 1, NAME_FLAG) + name[:8]  # byte length, byte type, value
        self._ble.gap_advertise(interval_us, adv_data=payload)
        
    def stop_advertising(self):
        self._ble.gap_advertise(None)

class Sniff: 
    def __init__(self): 
        self._ble = bluetooth.BLE()
        self._ble.active(True)
        self._ble.irq(self._irq)
        self.scanning = False 
        self.names = []
        self.command = 5

    def _irq(self, event, data):
        if event == IRQ_SCAN_RESULT: #check to see if it is a serialperipheral
            addr_type, addr, adv_type, rssi, adv_data = data
            name = self.decode_name(adv_data)
            #print('.',end='')
            if name == '':
                return
            if name[0] != '~':
                return
            self.command = int(name[1])

        elif event == IRQ_SCAN_DONE:  # close everything
            self.scanning = False

    def decode_field(self, payload, adv_type):
        i = 0
        result = []
        while i + 1 < len(payload):
            if payload[i + 1] == adv_type:
                result.append(payload[i + 2 : i + payload[i] + 1])
            i += 1 + payload[i]
        return result
        
    def decode_name(self,payload):
        n = self.decode_field(payload, NAME_FLAG)
        return str(n[0], "utf-8") if n else ""

    def scan(self, duration = 2000):
        self.scanning = True
        #run for duration sec, with checking every 30 ms for 30 ms
        duration = 0 if duration < 0 else duration
        return self._ble.gap_scan(duration, 30000, 30000)

    def stop_scan(self):
        self._scan_callback = None
        self._ble.gap_scan(None)
        self.scanning = False